<?php | <?php |
/* | /* |
* Copyright 2010,2011 Alexander Sadleir | * Copyright 2010,2011 Alexander Sadleir |
Licensed under the Apache License, Version 2.0 (the "License"); | Licensed under the Apache License, Version 2.0 (the "License"); |
you may not use this file except in compliance with the License. | you may not use this file except in compliance with the License. |
You may obtain a copy of the License at | You may obtain a copy of the License at |
http://www.apache.org/licenses/LICENSE-2.0 | http://www.apache.org/licenses/LICENSE-2.0 |
Unless required by applicable law or agreed to in writing, software | Unless required by applicable law or agreed to in writing, software |
distributed under the License is distributed on an "AS IS" BASIS, | distributed under the License is distributed on an "AS IS" BASIS, |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
See the License for the specific language governing permissions and | See the License for the specific language governing permissions and |
limitations under the License. | limitations under the License. |
*/ | */ |
include ('include/common.inc.php'); | include ('include/common.inc.php'); |
include_header("About", "about") | include_header("About", "about") |
?> | ?> |
<p> | <p> |
Busness Time - An ACT bus timetable webapp<br /> | Busness Time - An ACT bus timetable webapp<br /> |
Based on the maxious-canberra-transit-feed (<a | Based on the maxious-canberra-transit-feed (<a |
href="http://busresources.lambdacomplex.org/cbrfeed.zip">download</a>, | href="http://busresources.lambdacomplex.org/cbrfeed.zip">download</a>, |
last updated <?php echo date("F d Y.", @filemtime('../busresources/cbrfeed.zip')); ?>)<br /> | last updated <?php echo date("F d Y.", @filemtime('../busresources/cbrfeed.zip')); ?>)<br /> |
Source code for the <a | Source code for the <a |
href="https://github.com/maxious/ACTBus-data">transit | href="https://github.com/maxious/ACTBus-data">transit |
feed</a> and <a href="https://github.com/maxious/ACTBus-ui">this | feed</a> and <a href="https://github.com/maxious/ACTBus-ui">this |
site</a> available from github.<br /> | site</a> available from github.<br /> |
Uses jQuery Mobile, PHP, PostgreSQL, OpenTripPlanner, OpenLayers, OpenStreetMap, Cloudmade Geocoder and Tile Service<br /> | Uses jQuery Mobile, PHP, PostgreSQL, OpenTripPlanner, OpenLayers, OpenStreetMap, Cloudmade Geocoder and Tile Service<br /> |
Suburb Geocoding Based on <A href="http://www.abs.gov.au/AUSSTATS/abs@.nsf/Lookup/1270.0.55.003Main+Features1July%202011?OpenDocument">Australian Bureau of Statistics data.</a><br /> | Suburb Geocoding Based on <A href="http://www.abs.gov.au/AUSSTATS/abs@.nsf/Lookup/1270.0.55.003Main+Features1July%202011?OpenDocument">Australian Bureau of Statistics data.</a><br /> |
Street geocoding based on work by OpenStreetMap contributors<br> | Street geocoding based on work by OpenStreetMap contributors<br> |
<br /> | <br /> |
Feedback encouraged; contact maxious@lambdacomplex.org<br /> | Feedback encouraged; contact maxious@lambdacomplex.org<br /> |
<br /> | <br /> |
Some icons by Joseph Wain / glyphish.com<br /> | Some icons by Joseph Wain / glyphish.com<br /> |
Native clients also available for iPhone(<a href="http://itunes.apple.com/au/app/cbrtimetable/id444287349?mt=8">cbrTimetable by Sandor Kolotenko</a> | Native clients also available for iPhone(<a href="http://itunes.apple.com/au/app/cbrtimetable/id444287349?mt=8">cbrTimetable by Sandor Kolotenko</a> |
, <a href="http://itunes.apple.com/au/app/act-buses/id376634797?mt=8">ACT Buses by David Sullivan</a>, <a href="http://itunes.apple.com/app/bus-trips-act/id489146525?mt=8">Bus Trips ACT by Molson Chengalath</a>) | , <a href="http://itunes.apple.com/au/app/act-buses/id376634797?mt=8">ACT Buses by David Sullivan</a>, <a href="http://itunes.apple.com/app/bus-trips-act/id489146525?mt=8">Bus Trips ACT by Molson Chengalath</a>) |
, Android (<a href="https://market.android.com/details?id=com.action">MyBus 2.0 by Imagine Team</a>, <A href="https://market.android.com/details?id=GetMe2CanberraFree.source">GetMe2 Canberra by | , Android (<a href="https://market.android.com/details?id=com.action">MyBus 2.0 by Imagine Team</a>, <A href="https://market.android.com/details?id=GetMe2CanberraFree.source">GetMe2 Canberra by |
Colin Thompson </a>) | Colin Thompson </a>, <a href="https://market.android.com/details?id=au.com.transittimes.android">TransitTimes+ by Zervaas Enterprises</a>) |
and Windows Phone 7 (<a href="http://www.windowsphone.com/en-AU/apps/d840375e-429c-4aa4-a358-80eec6ea9e66">TransHub Canberra by Soul Solutions</a>) Other web clients include <a href="http://canberra.itranzit.com/option.html">iTranzit</a>. | and Windows Phone 7 (<a href="http://www.windowsphone.com/en-AU/apps/d840375e-429c-4aa4-a358-80eec6ea9e66">TransHub Canberra by Soul Solutions</a>) Other web clients include <a href="http://canberra.itranzit.com/option.html">iTranzit</a>. |
<br /> | <br /> |
GTFS-realtime API: | GTFS-realtime API: |
Alerts and Trip Updates (but only Cancelled or Stop Skipped) | Alerts and Trip Updates (but only Cancelled or Stop Skipped) |
Default format binary Protocol Buffer but can get JSON by adding ?ascii=yes | Default format binary Protocol Buffer but can get JSON by adding ?ascii=yes |
<br /> | <br /> |
<br /> | <br /> |
<small>Disclaimer: The content of this website is of a general and informative nature. Please check with printed timetables or those available on http://action.act.gov.au before your trip. | <small>Disclaimer: The content of this website is of a general and informative nature. Please check with printed timetables or those available on http://action.act.gov.au before your trip. |
Whilst every effort has been made to ensure the high quality and accuracy of the Site, the Author makes no warranty, | Whilst every effort has been made to ensure the high quality and accuracy of the Site, the Author makes no warranty, |
express or implied concerning the topicality, correctness, completeness or quality of the information, which is provided | express or implied concerning the topicality, correctness, completeness or quality of the information, which is provided |
"as is". The Author expressly disclaims all warranties, including but not limited to warranties of fitness for a particular purpose and warranties of merchantability. | "as is". The Author expressly disclaims all warranties, including but not limited to warranties of fitness for a particular purpose and warranties of merchantability. |
All offers are not binding and without obligation. The Author expressly reserves the right, in his discretion, to suspend, | All offers are not binding and without obligation. The Author expressly reserves the right, in his discretion, to suspend, |
change, modify, add or remove portions of the Site and to restrict or terminate the use and accessibility of the Site | change, modify, add or remove portions of the Site and to restrict or terminate the use and accessibility of the Site |
without prior notice. </small> | without prior notice. </small> |
<?php | <?php |
include_footer(); | include_footer(); |
?> | ?> |
<?php | <?php |
/* | /* |
* Copyright 2010,2011 Alexander Sadleir | * Copyright 2010,2011 Alexander Sadleir |
Licensed under the Apache License, Version 2.0 (the "License"); | Licensed under the Apache License, Version 2.0 (the "License"); |
you may not use this file except in compliance with the License. | you may not use this file except in compliance with the License. |
You may obtain a copy of the License at | You may obtain a copy of the License at |
http://www.apache.org/licenses/LICENSE-2.0 | http://www.apache.org/licenses/LICENSE-2.0 |
Unless required by applicable law or agreed to in writing, software | Unless required by applicable law or agreed to in writing, software |
distributed under the License is distributed on an "AS IS" BASIS, | distributed under the License is distributed on an "AS IS" BASIS, |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
See the License for the specific language governing permissions and | See the License for the specific language governing permissions and |
limitations under the License. | limitations under the License. |
*/ | */ |
// Copyright 2009 Google Inc. All Rights Reserved. | // Copyright 2009 Google Inc. All Rights Reserved. |
$GA_ACCOUNT = "MO-22173039-1"; | $GA_ACCOUNT = "MO-22173039-1"; |
$GA_PIXEL = "/lib/ga.php"; | $GA_PIXEL = "/lib/ga.php"; |
function googleAnalyticsGetImageUrl() { | function googleAnalyticsGetImageUrl() { |
global $GA_ACCOUNT, $GA_PIXEL; | global $GA_ACCOUNT, $GA_PIXEL; |
//if (stristr($_SERVER['HTTP_USER_AGENT'], 'Googlebot') return ""; | //if (stristr($_SERVER['HTTP_USER_AGENT'], 'Googlebot') return ""; |
$url = ""; | $url = ""; |
$url.= $GA_PIXEL . "?"; | $url.= $GA_PIXEL . "?"; |
$url.= "utmac=" . $GA_ACCOUNT; | $url.= "utmac=" . $GA_ACCOUNT; |
$url.= "&utmn=" . rand(0, 0x7fffffff); | $url.= "&utmn=" . rand(0, 0x7fffffff); |
$referer = (isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : ""); | $referer = (isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : ""); |
$query = $_SERVER["QUERY_STRING"]; | $query = $_SERVER["QUERY_STRING"]; |
$path = $_SERVER["REQUEST_URI"]; | $path = $_SERVER["REQUEST_URI"]; |
if (empty($referer)) { | if (empty($referer)) { |
$referer = "-"; | $referer = "-"; |
} | } |
$url.= "&utmr=" . urlencode($referer); | $url.= "&utmr=" . urlencode($referer); |
if (!empty($path)) { | if (!empty($path)) { |
$url.= "&utmp=" . urlencode($path); | $url.= "&utmp=" . urlencode($path); |
} | } |
$url.= "&guid=ON"; | $url.= "&guid=ON"; |
return str_replace("&", "&", $url); | return str_replace("&", "&", $url); |
} | } |
function include_header($pageTitle, $pageType, $opendiv = true, $geolocate = false, $datepicker = false) { | function include_header($pageTitle, $pageType, $opendiv = true, $geolocate = false, $datepicker = false) { |
global $basePath, $GTFSREnabled, $stopid, $routeid; | global $basePath, $GTFSREnabled, $stopid, $routeid; |
echo ' | echo ' |
<!DOCTYPE html> | <!DOCTYPE html> |
<html lang="en"> | <html lang="en"> |
<head> | <head> |
<meta charset="UTF-8"> | <meta charset="UTF-8"> |
<meta name="viewport" content="width=device-width, initial-scale=1"> | <meta name="viewport" content="width=device-width, initial-scale=1"> |
<title>' . $pageTitle . ' - Canberra Bus Timetable</title> | <title>' . $pageTitle . ' - Canberra Bus Timetable</title> |
<meta name="google-site-verification" content="-53T5Qn4TB_de1NyfR_ZZkEVdUNcNFSaYKSFkWKx-sY" /> | <meta name="google-site-verification" content="-53T5Qn4TB_de1NyfR_ZZkEVdUNcNFSaYKSFkWKx-sY" /> |
<link rel="dns-prefetch" href="//code.jquery.com"> | <link rel="dns-prefetch" href="//code.jquery.com"> |
<link rel="dns-prefetch" href="//ajax.googleapis.com">'; | <link rel="dns-prefetch" href="//ajax.googleapis.com">'; |
$jqmVersion = "1.0.1"; | $jqmVersion = "1.0.1"; |
echo ' | echo ' |
<script src="js/yepnope/yepnope.1.5.3-min.js"></script> | <script src="'.$basePath.'js/yepnope/yepnope.1.5.3-min.js"></script> |
<script> | <script> |
yepnope([{ | yepnope([{ |
load: "//ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js", | load: "//ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js", |
complete: function () { | complete: function () { |
$(document).bind("mobileinit", function(){ | $(document).bind("mobileinit", function(){ |
$.mobile.ajaxEnabled = false; | $.mobile.ajaxEnabled = false; |
}); } | }); } |
}, { | }, { |
load: ["//code.jquery.com/mobile/' . $jqmVersion . '/jquery.mobile-' . $jqmVersion . '.min.css","//code.jquery.com/mobile/' . $jqmVersion . '/jquery.mobile-' . $jqmVersion . '.min.js"] | load: ["//code.jquery.com/mobile/' . $jqmVersion . '/jquery.mobile-' . $jqmVersion . '.min.css","//code.jquery.com/mobile/' . $jqmVersion . '/jquery.mobile-' . $jqmVersion . '.min.js"] |
}, { | }, { |
load: ["' . $basePath . 'css/jquery-ui-1.8.12.custom.css","' . $basePath . 'js/jquery.ui.core.min.js","' . $basePath . 'js/jquery.ui.position.min.js","' . $basePath . 'js/jquery.ui.widget.min.js","' . $basePath . 'js/jquery.ui.autocomplete.min.js"], | load: ["' . $basePath . 'css/jquery-ui-1.8.12.custom.css","' . $basePath . 'js/jquery.ui.core.min.js","' . $basePath . 'js/jquery.ui.position.min.js","' . $basePath . 'js/jquery.ui.widget.min.js","' . $basePath . 'js/jquery.ui.autocomplete.min.js"], |
complete: function() { | complete: function() { |
$( "#geolocate" ).autocomplete({ | $( "#geolocate" ).autocomplete({ |
source: "lib/autocomplete.php", | source: "lib/autocomplete.php", |
minLength: 2 | minLength: 2 |
}); | }); |
$( "#from" ).autocomplete({ | $( "#from" ).autocomplete({ |
source: "lib/autocomplete.php", | source: "lib/autocomplete.php", |
minLength: 2 | minLength: 2 |
}); | }); |
$( "#to" ).autocomplete({ | $( "#to" ).autocomplete({ |
source: "lib/autocomplete.php", | source: "lib/autocomplete.php", |
minLength: 2 | minLength: 2 |
}); | }); |
} | } |
}]); | }]); |
</script> | </script> |
'; | '; |
echo '<style type="text/css">'; | echo '<style type="text/css">'; |
if (strstr($_SERVER['HTTP_USER_AGENT'], 'Android')) | if (strstr($_SERVER['HTTP_USER_AGENT'], 'Android')) |
echo '.ui-shadow,.ui-btn-up-a,.ui-btn-hover-a,.ui-btn-down-a,.ui-body-b,.ui-btn-up-b,.ui-btn-hover-b, | echo '.ui-shadow,.ui-btn-up-a,.ui-btn-hover-a,.ui-btn-down-a,.ui-body-b,.ui-btn-up-b,.ui-btn-hover-b, |
.ui-btn-down-b,.ui-bar-c,.ui-body-c,.ui-btn-up-c,.ui-btn-hover-c,.ui-btn-down-c,.ui-bar-c,.ui-body-d, | .ui-btn-down-b,.ui-bar-c,.ui-body-c,.ui-btn-up-c,.ui-btn-hover-c,.ui-btn-down-c,.ui-bar-c,.ui-body-d, |
.ui-btn-up-d,.ui-btn-hover-d,.ui-btn-down-d,.ui-bar-d,.ui-body-e,.ui-btn-up-e,.ui-btn-hover-e, | .ui-btn-up-d,.ui-btn-hover-d,.ui-btn-down-d,.ui-bar-d,.ui-body-e,.ui-btn-up-e,.ui-btn-hover-e, |
.ui-btn-down-e,.ui-bar-e,.ui-overlay-shadow,.ui-shadow,.ui-btn-active,.ui-body-a,.ui-bar-a { | .ui-btn-down-e,.ui-bar-e,.ui-overlay-shadow,.ui-shadow,.ui-btn-active,.ui-body-a,.ui-bar-a { |
text-shadow: none; | text-shadow: none; |
box-shadow: none; | box-shadow: none; |
-webkit-box-shadow: none; | -webkit-box-shadow: none; |
}'; | }'; |
echo '</style>'; | echo '</style>'; |
echo '<link rel="stylesheet" href="' . $basePath . 'css/local.css.php" />'; | echo '<link rel="stylesheet" href="' . $basePath . 'css/local.css.php" />'; |
if (isIOSDevice()) { | if (isIOSDevice()) { |
echo '<meta name="apple-mobile-web-app-capable" content="yes" /> | echo '<meta name="apple-mobile-web-app-capable" content="yes" /> |
<meta name="apple-mobile-web-app-status-bar-style" content="black" /> | <meta name="apple-mobile-web-app-status-bar-style" content="black" /> |
<link rel="apple-touch-startup-image" href="startup.png" /> | <link rel="apple-touch-startup-image" href="startup.png" /> |
<link rel="apple-touch-icon" href="apple-touch-icon.png" />'; | <link rel="apple-touch-icon" href="apple-touch-icon.png" />'; |
} | } |
if ($geolocate) { | if ($geolocate) { |
echo "<script> | echo "<script> |
function success(position) { | function success(position) { |
$('#error').val('Location now detected. Please wait for data to load.'); | $('#error').val('Location now detected. Please wait for data to load.'); |
$('#geolocate').val(position.coords.latitude+','+position.coords.longitude); | $('#geolocate').val(position.coords.latitude+','+position.coords.longitude); |
$.ajax({ async: false, | $.ajax({ async: false, |
success: function(){ | success: function(){ |
location.reload(true); | location.reload(true); |
}, | }, |
url: \"include/common.inc.php?geolocate=yes&lat=\"+position.coords.latitude+\"&lon=\"+position.coords.longitude }); | url: \"include/common.inc.php?geolocate=yes&lat=\"+position.coords.latitude+\"&lon=\"+position.coords.longitude }); |
} | } |
function error(msg) { | function error(msg) { |
$('#error').val('Error: '+msg); | $('#error').val('Error: '+msg); |
} | } |
function geolocate() { | function geolocate() { |
if (navigator.geolocation) { | if (navigator.geolocation) { |
var options = { | var options = { |
enableHighAccuracy: true, | enableHighAccuracy: true, |
timeout: 60000, | timeout: 60000, |
maximumAge: 10000 | maximumAge: 10000 |
} | } |
navigator.geolocation.getCurrentPosition(success, error, options); | navigator.geolocation.getCurrentPosition(success, error, options); |
} | } |
} | } |
$(document).ready(function() { | $(document).ready(function() { |
$('#here').click(function(event) { $('#geolocate').val(geolocate()); return false;}); | $('#here').click(function(event) { $('#geolocate').val(geolocate()); return false;}); |
$('#here').show(); | $('#here').show(); |
}); | }); |
"; | "; |
if (!isset($_SESSION['lat']) || $_SESSION['lat'] == "") | if (!isset($_SESSION['lat']) || $_SESSION['lat'] == "") |
echo "geolocate();"; | echo "geolocate();"; |
echo "</script> "; | echo "</script> "; |
} | } |
if (isAnalyticsOn()) | if (isAnalyticsOn()) |
echo ' | echo ' |
<script type="text/javascript">' . " | <script type="text/javascript">' . " |
var _gaq = _gaq || []; | var _gaq = _gaq || []; |
_gaq.push(['_setAccount', 'UA-22173039-1']); | _gaq.push(['_setAccount', 'UA-22173039-1']); |
_gaq.push(['_trackPageview']); | _gaq.push(['_trackPageview']); |
_gaq.push(['_trackPageLoadTime']); | _gaq.push(['_trackPageLoadTime']); |
</script>"; | </script>"; |
echo '</head> | echo '</head> |
<body> | <body> |
<div id="skip"> | <div id="skip"> |
<a href="#maincontent">Skip to content</a> | <a href="#maincontent">Skip to content</a> |
</div> | </div> |
'; | '; |
if ($opendiv) { | if ($opendiv) { |
echo '<div data-role="page"> | echo '<div data-role="page"> |
<div data-role="header" data-position="inline"> | <div data-role="header" data-position="inline"> |
<a href="' . (isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : "javascript:history.go(-1)") . '" data-icon="arrow-l" data-rel="back" class="ui-btn-left">Back</a> | <a href="' . (isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : "javascript:history.go(-1)") . '" data-icon="arrow-l" data-rel="back" class="ui-btn-left">Back</a> |
<h1>' . $pageTitle . '</h1> | <h1>' . $pageTitle . '</h1> |
<a href="' . $basePath . '/index.php" data-icon="home" class="ui-btn-right">Home</a> | <a href="' . $basePath . '/index.php" data-icon="home" class="ui-btn-right">Home</a> |
</div><!-- /header --> | </div><!-- /header --> |
<a name="maincontent" id="maincontent"></a> | <a name="maincontent" id="maincontent"></a> |
<div data-role="content"> '; | <div data-role="content"> '; |
if ($GTFSREnabled) { | if ($GTFSREnabled) { |
$overrides = getServiceOverride(); | $overrides = getServiceOverride(); |
if (isset($overrides['service_id'])) { | if (isset($overrides['service_id'])) { |
if ($overrides['service_id'] == "noservice") { | if ($overrides['service_id'] == "noservice") { |
echo '<div class="servicewarning">Buses are <strong>not running today</strong> due to industrial action/public holiday. See <a | echo '<div class="servicewarning">Buses are <strong>not running today</strong> due to industrial action/public holiday. See <a |
href="http://www.action.act.gov.au">http://www.action.act.gov.au</a> for details.</div>'; | href="http://www.action.act.gov.au">http://www.action.act.gov.au</a> for details.</div>'; |
} else { | } else { |
echo '<div class="servicewarning">Buses are running on an altered timetable today due to industrial action/public holiday. See <a href="http://www.action.act.gov.au">http://www.action.act.gov.au</a> for details.</div>'; | echo '<div class="servicewarning">Buses are running on an altered timetable today due to industrial action/public holiday. See <a href="http://www.action.act.gov.au">http://www.action.act.gov.au</a> for details.</div>'; |
} | } |
} | } |
$serviceAlerts = Array(); | $serviceAlerts = Array(); |
$globalAlerts = getServiceAlertsAsArray("agency", "0"); | $globalAlerts = getServiceAlertsAsArray("agency", "0"); |
if ($globalAlerts != null) { | if ($globalAlerts != null) { |
// echo "getting alerts due to network wide"; | // echo "getting alerts due to network wide"; |
$serviceAlerts = array_merge($serviceAlerts, $globalAlerts); | $serviceAlerts = array_merge($serviceAlerts, $globalAlerts); |
} | } |
if (isset($stopid)) { | if (isset($stopid)) { |
$stopAlerts = getServiceAlertsAsArray("stop", $stopid); | $stopAlerts = getServiceAlertsAsArray("stop", $stopid); |
if ($stopAlerts != null) { | if ($stopAlerts != null) { |
// echo "getting alerts due to stop $stopid"; | // echo "getting alerts due to stop $stopid"; |
$serviceAlerts = array_merge($serviceAlerts, $stopAlerts); | $serviceAlerts = array_merge($serviceAlerts, $stopAlerts); |
} | } |
} | } |
if (isset($routeid)) { | if (isset($routeid)) { |
$routeAlerts = getServiceAlertsAsArray("route", $routeid); | $routeAlerts = getServiceAlertsAsArray("route", $routeid); |
if ($routeAlerts != null) { | if ($routeAlerts != null) { |
// echo "getting alerts due to route $routeid"; | // echo "getting alerts due to route $routeid"; |
$serviceAlerts = array_merge($serviceAlerts, $routeAlerts); | $serviceAlerts = array_merge($serviceAlerts, $routeAlerts); |
} | } |
} | } |
if (isset($serviceAlerts['entity']) && sizeof($serviceAlerts['entity']) > 0) { | if (isset($serviceAlerts['entity']) && sizeof($serviceAlerts['entity']) > 0) { |
foreach ($serviceAlerts['entity'] as $entity) { | foreach ($serviceAlerts['entity'] as $entity) { |
echo "<div class='servicewarning'><b>{$entity['alert']['header_text']['translation'][0]['text']}</b> <small>" | echo "<div class='servicewarning'><b>{$entity['alert']['header_text']['translation'][0]['text']}</b> <small>" |
. date("F jS Y, g:i a", $entity['alert']['active_period'][0]['start']) . " to " | . date("F jS Y, g:i a", $entity['alert']['active_period'][0]['start']) . " to " |
. date("F jS Y, g:i a", $entity['alert']['active_period'][0]['end']) . "</small> | . date("F jS Y, g:i a", $entity['alert']['active_period'][0]['end']) . "</small> |
<br>Warning: {$entity['alert']['description_text']['translation'][0]['text']} | <br>Warning: {$entity['alert']['description_text']['translation'][0]['text']} |
<br><a href='{$entity['alert']['url']['translation'][0]['text']}'>Source</a> </div>"; | <br><a href='{$entity['alert']['url']['translation'][0]['text']}'>Source</a> </div>"; |
} | } |
} | } |
} | } |
} | } |
} | } |
function include_footer() { | function include_footer() { |
global $basePath; | global $basePath; |
echo '<div id="footer"><a href="' . $basePath . 'about.php">About/Contact Us</a> <a href="' . $basePath . 'feedback.php">Feedback/Bug Report</a> <a href="' . $basePath . 'privacy.php">Privacy Policy</a>'; | echo '<div id="footer"><a href="' . $basePath . 'about.php">About/Contact Us</a> <a href="' . $basePath . 'feedback.php">Feedback/Bug Report</a> <a href="' . $basePath . 'privacy.php">Privacy Policy</a>'; |
echo '</div>'; | echo '</div>'; |
if (isAnalyticsOn()) { | if (isAnalyticsOn()) { |
echo "<script> (function() { | echo "<script> (function() { |
var ga = document.createElement('script'); ga.type = | var ga = document.createElement('script'); ga.type = |
'text/javascript'; ga.async = true; | 'text/javascript'; ga.async = true; |
ga.src = ('https:' == document.location.protocol ? | ga.src = ('https:' == document.location.protocol ? |
'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; | 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; |
var s = document.getElementsByTagName('script')[0]; | var s = document.getElementsByTagName('script')[0]; |
s.parentNode.insertBefore(ga, s); | s.parentNode.insertBefore(ga, s); |
})();</script>"; | })();</script>"; |
$googleAnalyticsImageUrl = googleAnalyticsGetImageUrl(); | $googleAnalyticsImageUrl = googleAnalyticsGetImageUrl(); |
echo '<noscript><img src="' . $googleAnalyticsImageUrl . '" alt=""/></noscript>'; | echo '<noscript><img src="' . $googleAnalyticsImageUrl . '" alt=""/></noscript>'; |
} | } |
echo "\n</div></div></body></html>"; | echo "\n</div></div></body></html>"; |
} | } |
function timeSettings() { | function timeSettings() { |
global $service_periods; | global $service_periods; |
echo '<div id="settings" data-role="collapsible" data-collapsed="true"> | echo '<div id="settings" data-role="collapsible" data-collapsed="true"> |
<h3>Change Time (' . (isset($_REQUEST['time']) ? $_REQUEST['time'] : "Current Time,") . ' ' . ucwords(service_period()) . ')...</h3> | <h3>Change Time (' . (isset($_REQUEST['time']) ? $_REQUEST['time'] : "Current Time,") . ' ' . ucwords(service_period()) . ')...</h3> |
<form action="' . basename($_SERVER['PHP_SELF']) . '" method="GET"> | <form action="' . basename($_SERVER['PHP_SELF']) . '" method="GET"> |
<input type="hidden" name="suburb" id="suburb" value="' . (isset($_REQUEST['suburb']) ? $_REQUEST['suburb'] : "") . '"/> | <input type="hidden" name="suburb" id="suburb" value="' . (isset($_REQUEST['suburb']) ? $_REQUEST['suburb'] : "") . '"/> |
<input type="hidden" name="stopid" id="stopid" value="' . (isset($_REQUEST['stopid']) ? $_REQUEST['stopid'] : "") . '"/> | <input type="hidden" name="stopid" id="stopid" value="' . (isset($_REQUEST['stopid']) ? $_REQUEST['stopid'] : "") . '"/> |
<input type="hidden" name="stopcode" id="stopcode" value="' . (isset($_REQUEST['stopcode']) ? $_REQUEST['stopcode'] : "") . '"/> | <input type="hidden" name="stopcode" id="stopcode" value="' . (isset($_REQUEST['stopcode']) ? $_REQUEST['stopcode'] : "") . '"/> |
<div class="ui-body"> | <div class="ui-body"> |
<div data-role="fieldcontain"> | <div data-role="fieldcontain"> |
<label for="time"> Time: </label> | <label for="time"> Time: </label> |
<input type="time" name="time" id="time" value="' . (isset($_REQUEST['time']) ? $_REQUEST['time'] : date("H:i")) . '"/> | <input type="time" name="time" id="time" value="' . (isset($_REQUEST['time']) ? $_REQUEST['time'] : date("H:i")) . '"/> |
<a href="#" name="currentTime" id="currentTime" onClick="var d = new Date();' . "$('#time').val(d.getHours() +':'+ (d.getMinutes().toString().length == 1 ? '0'+ d.getMinutes(): d.getMinutes()));" . '">Current Time?</a> | <a href="#" name="currentTime" id="currentTime" onClick="var d = new Date();' . "$('#time').val(d.getHours() +':'+ (d.getMinutes().toString().length == 1 ? '0'+ d.getMinutes(): d.getMinutes()));" . '">Current Time?</a> |
</div> | </div> |
<div data-role="fieldcontain"> | <div data-role="fieldcontain"> |
<label for="service_period"> Service Period: </label> | <label for="service_period"> Service Period: </label> |
<select name="service_period" id="service_period">'; | <select name="service_period" id="service_period">'; |
foreach ($service_periods as $service_period) { | foreach ($service_periods as $service_period) { |
echo "<option value=\"$service_period\"" . (service_period() === $service_period ? " SELECTED" : "") . '>' . ucwords($service_period) . '</option>'; | echo "<option value=\"$service_period\"" . (service_period() === $service_period ? " SELECTED" : "") . '>' . ucwords($service_period) . '</option>'; |
} | } |
echo '</select> | echo '</select> |
<a href="#" style="display:none" name="currentPeriod" id="currentPeriod">Current Period?</a> | <a href="#" style="display:none" name="currentPeriod" id="currentPeriod">Current Period?</a> |
</div> | </div> |
<input type="submit" value="Update"/> | <input type="submit" value="Update"/> |
</div></form> | </div></form> |
</div>'; | </div>'; |
} | } |
function placeSettings() { | function placeSettings() { |
$geoerror = false; | $geoerror = false; |
$geoerror = !isset($_SESSION['lat']) || !isset($_SESSION['lat']) || $_SESSION['lat'] == "" || $_SESSION['lon'] == ""; | $geoerror = !isset($_SESSION['lat']) || !isset($_SESSION['lat']) || $_SESSION['lat'] == "" || $_SESSION['lon'] == ""; |
echo '<div id="error">'; | echo '<div id="error">'; |
if ($geoerror) { | if ($geoerror) { |
echo 'Sorry, but your location could not currently be detected. | echo 'Sorry, but your location could not currently be detected. |
Please allow location permission, wait for your location to be detected, | Please allow location permission, wait for your location to be detected, |
or enter an address/co-ordinates in the box below.'; | or enter an address/co-ordinates in the box below.'; |
} | } |
echo '</div>'; | echo '</div>'; |
echo '<div id="settings" data-role="collapsible" data-collapsed="' . !$geoerror . '"> | echo '<div id="settings" data-role="collapsible" data-collapsed="' . !$geoerror . '"> |
<h3>Change Location...</h3> | <h3>Change Location...</h3> |
<form action="' . basename($_SERVER['PHP_SELF']) . "?" . $_SERVER['QUERY_STRING'] . '" method="post"> | <form action="' . basename($_SERVER['PHP_SELF']) . "?" . $_SERVER['QUERY_STRING'] . '" method="post"> |
<div class="ui-body"> | <div class="ui-body"> |
<div data-role="fieldcontain"> | <div data-role="fieldcontain"> |
<label for="geolocate"> Current Location: </label> | <label for="geolocate"> Current Location: </label> |
<input type="text" id="geolocate" name="geolocate" value="' . (isset($_SESSION['lat']) && isset($_SESSION['lon']) ? $_SESSION['lat'] . "," . $_SESSION['lon'] : "Enter co-ordinates or address here") . '"/> <a href="#" style="display:none" name="here" id="here">Here?</a> | <input type="text" id="geolocate" name="geolocate" value="' . (isset($_SESSION['lat']) && isset($_SESSION['lon']) ? $_SESSION['lat'] . "," . $_SESSION['lon'] : "Enter co-ordinates or address here") . '"/> <a href="#" style="display:none" name="here" id="here">Here?</a> |
</div> | </div> |
<input type="submit" value="Update"/> | <input type="submit" value="Update"/> |
</div></form> | </div></form> |
</div>'; | </div>'; |
} | } |
function trackEvent($category, $action, $label = "", $value = - 1) { | function trackEvent($category, $action, $label = "", $value = - 1) { |
if (isAnalyticsOn()) { | if (isAnalyticsOn()) { |
echo "\n<script> _gaq.push(['_trackEvent', '$category', '$action'" . ($label != "" ? ", '$label'" : "") . ($value != - 1 ? ", $value" : "") . "]);</script>"; | echo "\n<script> _gaq.push(['_trackEvent', '$category', '$action'" . ($label != "" ? ", '$label'" : "") . ($value != - 1 ? ", $value" : "") . "]);</script>"; |
} | } |
} | } |
//stop list collapsing | //stop list collapsing |
function stopCompare($stopName) { | function stopCompare($stopName) { |
return substr(trim(preg_replace("/\(Platform.*/", "", $stopName)), 0, 9); | return substr(trim(preg_replace("/\(Platform.*/", "", $stopName)), 0, 9); |
} | } |
function stopGroupTitle($stopName, $stopdesc) { | function stopGroupTitle($stopName, $stopdesc) { |
if (preg_match("/Dr |Cct |Cir |Av |St |Cr |Parade |Way |Bank /", $stopName)) { | if (preg_match("/Dr |Cct |Cir |Av |St |Cr |Parade |Way |Bank /", $stopName)) { |
$descParts = explode("<br>", $stopdesc); | $descParts = explode("<br>", $stopdesc); |
return trim(str_replace("Street: ", "", $descParts[0])); | return trim(str_replace("Street: ", "", $descParts[0])); |
} else { | } else { |
return trim(preg_replace("/\(Platform.*/", "", $stopName)); | return trim(preg_replace("/\(Platform.*/", "", $stopName)); |
} | } |
} | } |
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) { |
if (strstr($point['stop_name'], "Station") | if (strstr($point['stop_name'], "Station") |
|| strstr($point['stop_name'], "Shops") | || strstr($point['stop_name'], "Shops") |
|| strstr($point['stop_name'], "CIT") | || strstr($point['stop_name'], "CIT") |
|| strstr($point['stop_name'], "School") | || strstr($point['stop_name'], "School") |
|| strstr($point['stop_name'], "University") | || strstr($point['stop_name'], "University") |
) { | ) { |
$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 |
/* | /* |
* Copyright 2010,2011 Alexander Sadleir | * Copyright 2010,2011 Alexander Sadleir |
Licensed under the Apache License, Version 2.0 (the "License"); | Licensed under the Apache License, Version 2.0 (the "License"); |
you may not use this file except in compliance with the License. | you may not use this file except in compliance with the License. |
You may obtain a copy of the License at | You may obtain a copy of the License at |
http://www.apache.org/licenses/LICENSE-2.0 | http://www.apache.org/licenses/LICENSE-2.0 |
Unless required by applicable law or agreed to in writing, software | Unless required by applicable law or agreed to in writing, software |
distributed under the License is distributed on an "AS IS" BASIS, | distributed under the License is distributed on an "AS IS" BASIS, |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
See the License for the specific language governing permissions and | See the License for the specific language governing permissions and |
limitations under the License. | limitations under the License. |
*/ | */ |
function getServiceOverride($date = "") { | function getServiceOverride($date = "") { |
global $conn; | global $conn; |
$query = "Select * from calendar_dates where date = :date and exception_type = '1' LIMIT 1"; | $query = "Select * from calendar_dates where date = :date and exception_type = '1' LIMIT 1"; |
// debug($query,"database"); | // debug($query,"database"); |
$query = $conn->prepare($query); // Create a prepared statement | $query = $conn->prepare($query); // Create a prepared statement |
$query->bindParam(":date", date("Ymd", ($date != "" ? $date : time()))); | $date = date("Ymd", ($date != "" ? $date : time())); |
$query->bindParam(":date", $date); | |
$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 getServiceAlert($alertID) { | function getServiceAlert($alertID) { |
global $conn; | global $conn; |
$query = "SELECT id,extract('epoch' from start) as start, extract('epoch' from \"end\") as \"end\",cause,effect,header,description,url from servicealerts_alerts where id = :servicealert_id"; | $query = "SELECT id,extract('epoch' from start) as start, extract('epoch' from \"end\") as \"end\",cause,effect,header,description,url from servicealerts_alerts where id = :servicealert_id"; |
debug($query, "database"); | debug($query, "database"); |
$query = $conn->prepare($query); | $query = $conn->prepare($query); |
$query->bindParam(":servicealert_id", $alertID); | $query->bindParam(":servicealert_id", $alertID); |
$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 updateServiceAlert($alertID, $alert) { | function updateServiceAlert($alertID, $alert) { |
global $conn; | global $conn; |
$query = 'update servicealerts_alerts set start=:start, "end"=:end, header=:header, description=:description, url=:url, cause=:cause, effect=:effect where id = :servicealert_id'; | $query = 'update servicealerts_alerts set start=:start, "end"=:end, header=:header, description=:description, url=:url, cause=:cause, effect=:effect where id = :servicealert_id'; |
debug($query, "database"); | debug($query, "database"); |
$query = $conn->prepare($query); | $query = $conn->prepare($query); |
$query->bindValue(":servicealert_id", $alertID); | $query->bindValue(":servicealert_id", $alertID); |
$query->bindValue(":start", $alert['startdate']); | $query->bindValue(":start", $alert['startdate']); |
$query->bindValue(":end", $alert['enddate']); | $query->bindValue(":end", $alert['enddate']); |
$query->bindValue(":header", $alert['header']); | $query->bindValue(":header", $alert['header']); |
$query->bindValue(":description", $alert['description']); | $query->bindValue(":description", $alert['description']); |
$query->bindValue(":url", $alert['url']); | $query->bindValue(":url", $alert['url']); |
$query->bindValue(":cause", $alert['cause']); | $query->bindValue(":cause", $alert['cause']); |
$query->bindValue(":effect", $alert['effect']); | $query->bindValue(":effect", $alert['effect']); |
$query->execute(); | $query->execute(); |
print_r($conn->errorInfo()); | print_r($conn->errorInfo()); |
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 addServiceAlert($alert) { | function addServiceAlert($alert) { |
global $conn; | global $conn; |
$query = 'INSERT INTO servicealerts_alerts (start, "end", header, description, url,cause,effect) VALUES (:start, :end, :header, :description, :url,:cause,:effect) '; | $query = 'INSERT INTO servicealerts_alerts (start, "end", header, description, url,cause,effect) VALUES (:start, :end, :header, :description, :url,:cause,:effect) '; |
debug($query, "database"); | debug($query, "database"); |
$query = $conn->prepare($query); | $query = $conn->prepare($query); |
//print_r($alert); | //print_r($alert); |
$query->bindValue(":start", $alert['startdate']); | $query->bindValue(":start", $alert['startdate']); |
$query->bindValue(":end", $alert['enddate']); | $query->bindValue(":end", $alert['enddate']); |
$query->bindValue(":header", $alert['header']); | $query->bindValue(":header", $alert['header']); |
$query->bindValue(":description", $alert['description']); | $query->bindValue(":description", $alert['description']); |
$query->bindValue(":url", $alert['url']); | $query->bindValue(":url", $alert['url']); |
$query->bindValue(":cause", $alert['cause']); | $query->bindValue(":cause", $alert['cause']); |
$query->bindValue(":effect", $alert['effect']); | $query->bindValue(":effect", $alert['effect']); |
$query->execute(); | $query->execute(); |
print_r($conn->errorInfo()); | print_r($conn->errorInfo()); |
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 getCurrentAlerts() { | function getCurrentAlerts() { |
global $conn; | global $conn; |
$query = "SELECT id,extract('epoch' from start) as start, extract('epoch' from \"end\") as \"end\",cause,effect,header,description,url from servicealerts_alerts where NOW() > start and NOW() < \"end\""; | $query = "SELECT id,extract('epoch' from start) as start, extract('epoch' from \"end\") as \"end\",cause,effect,header,description,url from servicealerts_alerts where NOW() > start and NOW() < \"end\""; |
// debug($query, "database"); | // debug($query, "database"); |
$query = $conn->prepare($query); | $query = $conn->prepare($query); |
$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 getFutureAlerts() { | function getFutureAlerts() { |
global $conn; | global $conn; |
$query = "SELECT id,extract('epoch' from start) as start, extract('epoch' from \"end\") as \"end\",cause,effect,header,description,url from servicealerts_alerts where NOW() > start or NOW() < \"end\""; | $query = "SELECT id,extract('epoch' from start) as start, extract('epoch' from \"end\") as \"end\",cause,effect,header,description,url from servicealerts_alerts where NOW() > start or NOW() < \"end\""; |
// debug($query, "database"); | // debug($query, "database"); |
$query = $conn->prepare($query); | $query = $conn->prepare($query); |
$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 getInformedAlerts($id, $filter_class, $filter_id) { | function getInformedAlerts($id, $filter_class, $filter_id) { |
global $conn; | global $conn; |
//echo "$id, $filter_class, $filter_id\n"; | //echo "$id, $filter_class, $filter_id\n"; |
$query = "SELECT * from servicealerts_informed where servicealert_id = :servicealert_id"; | $query = "SELECT * from servicealerts_informed where servicealert_id = :servicealert_id"; |
if ($filter_class != "") { | if ($filter_class != "") { |
$query .= " AND informed_class = :informed_class "; | $query .= " AND informed_class = :informed_class "; |
} | } |
if ($filter_id != "") { | if ($filter_id != "") { |
$query .= " AND informed_id = :informed_id "; | $query .= " AND informed_id = :informed_id "; |
} | } |
// debug($query, "database"); | // debug($query, "database"); |
$query = $conn->prepare($query); | $query = $conn->prepare($query); |
if ($filter_class != "") { | if ($filter_class != "") { |
$query->bindParam(":informed_class", $filter_class); | $query->bindParam(":informed_class", $filter_class); |
} | } |
if ($filter_id != "") { | if ($filter_id != "") { |
$query->bindParam(":informed_id", $filter_id); | $query->bindParam(":informed_id", $filter_id); |
} | } |
$query->bindParam(":servicealert_id", $id); | $query->bindParam(":servicealert_id", $id); |
$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 deleteInformedAlert($serviceAlertID, $class, $id) { | function deleteInformedAlert($serviceAlertID, $class, $id) { |
global $conn; | global $conn; |
$query = 'DELETE from servicealerts_informed where servicealert_id = :servicealert_id and informed_class = :informed_class AND informed_id = :informed_id'; | $query = 'DELETE from servicealerts_informed where servicealert_id = :servicealert_id and informed_class = :informed_class AND informed_id = :informed_id'; |
debug($query, "database"); | debug($query, "database"); |
$query = $conn->prepare($query); | $query = $conn->prepare($query); |
$query->bindParam(":servicealert_id", $serviceAlertID); | $query->bindParam(":servicealert_id", $serviceAlertID); |
$query->bindParam(":informed_class", $class); | $query->bindParam(":informed_class", $class); |
$query->bindParam(":informed_id", $id); | $query->bindParam(":informed_id", $id); |
$query->execute(); | $query->execute(); |
print_r($conn->errorInfo()); | print_r($conn->errorInfo()); |
if (!$query) { | if (!$query) { |
databaseError($conn->errorInfo()); | databaseError($conn->errorInfo()); |
return Array(); | return Array(); |
} | } |
return null; | return null; |
} | } |
function addInformedAlert($serviceAlertID, $class, $id, $action) { | function addInformedAlert($serviceAlertID, $class, $id, $action) { |
global $conn; | global $conn; |
$query = 'INSERT INTO servicealerts_informed (servicealert_id , informed_class , informed_id, informed_action) | $query = 'INSERT INTO servicealerts_informed (servicealert_id , informed_class , informed_id, informed_action) |
VALUES(:servicealert_id ,:informed_class, :informed_id, :informed_action)'; | VALUES(:servicealert_id ,:informed_class, :informed_id, :informed_action)'; |
debug($query, "database"); | debug($query, "database"); |
$query = $conn->prepare($query); | $query = $conn->prepare($query); |
$query->bindParam(":servicealert_id", $serviceAlertID); | $query->bindParam(":servicealert_id", $serviceAlertID); |
$query->bindParam(":informed_class", $class); | $query->bindParam(":informed_class", $class); |
$query->bindParam(":informed_id", $id); | $query->bindParam(":informed_id", $id); |
$query->bindParam(":informed_action", $action); | $query->bindParam(":informed_action", $action); |
$query->execute(); | $query->execute(); |
print_r($conn->errorInfo()); | print_r($conn->errorInfo()); |
if (!$query) { | if (!$query) { |
databaseError($conn->errorInfo()); | databaseError($conn->errorInfo()); |
return Array(); | return Array(); |
} | } |
return null; | return null; |
} | } |
<?php | <?php |
include ('../include/common.inc.php'); | include ('../include/common.inc.php'); |
$debugOkay = Array(); // disable debugging output even on dev server | $debugOkay = Array(); // disable debugging output even on dev server |
/* | /* |
*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 ($basePath . 'lib/GoogleMapUtility.php'); |
require_once ($labsPath . 'lib/HeatMap.php'); | require_once ($basePath . '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; |
$spots = Array(); | $spots = Array(); |
$query = $conn->prepare($query); | $query = $conn->prepare($query); |
$query->execute(); | $query->execute(); |
if (!$query) { | if (!$query) { |
databaseError($conn->errorInfo()); | databaseError($conn->errorInfo()); |
return Array(); | return Array(); |
} | } |
foreach( $query->fetchAll() 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 |
?> | ?> |
<?php | <?php |
/* | /* |
* Copyright 2010,2011 Alexander Sadleir | * Copyright 2010,2011 Alexander Sadleir |
Licensed under the Apache License, Version 2.0 (the "License"); | Licensed under the Apache License, Version 2.0 (the "License"); |
you may not use this file except in compliance with the License. | you may not use this file except in compliance with the License. |
You may obtain a copy of the License at | You may obtain a copy of the License at |
http://www.apache.org/licenses/LICENSE-2.0 | http://www.apache.org/licenses/LICENSE-2.0 |
Unless required by applicable law or agreed to in writing, software | Unless required by applicable law or agreed to in writing, software |
distributed under the License is distributed on an "AS IS" BASIS, | distributed under the License is distributed on an "AS IS" BASIS, |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
See the License for the specific language governing permissions and | See the License for the specific language governing permissions and |
limitations under the License. | limitations under the License. |
*/ | */ |
header('Content-type: application/vnd.google-earth.kml+xml'); | header('Content-type: application/vnd.google-earth.kml+xml'); |
//http://wiki.openstreetmap.org/wiki/OpenLayers_Dynamic_KML | //http://wiki.openstreetmap.org/wiki/OpenLayers_Dynamic_KML |
// Creates the KML/XML Document. | // Creates the KML/XML Document. |
$dom = new DOMDocument('1.0', 'UTF-8'); | $dom = new DOMDocument('1.0', 'UTF-8'); |
// Creates the root KML element and appends it to the root document. | // Creates the root KML element and appends it to the root document. |
$node = $dom->createElementNS('http://earth.google.com/kml/2.1', 'kml'); | $node = $dom->createElementNS('http://earth.google.com/kml/2.1', 'kml'); |
$parNode = $dom->appendChild($node); | $parNode = $dom->appendChild($node); |
// Creates a KML Document element and append it to the KML element. | // Creates a KML Document element and append it to the KML element. |
$dnode = $dom->createElement('Document'); | $dnode = $dom->createElement('Document'); |
$docNode = $parNode->appendChild($dnode); | $docNode = $parNode->appendChild($dnode); |
$bbox = $_GET['bbox']; // get the bbox param from google earth | $bbox = $_GET['bbox']; // get the bbox param from google earth |
list($bbox_south, $bbox_west, $bbox_north, $bbox_east) = explode(",", $bbox); // west, south, east, north | list($bbox_south, $bbox_west, $bbox_north, $bbox_east) = explode(",", $bbox); // west, south, east, north |
include ('../include/common.inc.php'); | include ('../include/common.inc.php'); |
$debugOkay = Array(); // disable debugging output even on dev server | $debugOkay = Array(); // disable debugging output even on dev server |
//$contents = getNearbyStops((($bbox_west + $bbox_east) / 2), ($bbox_south + $bbox_north) / 2, 50, 3000); | $contents = getNearbyStops((($bbox_west + $bbox_east) / 2), ($bbox_south + $bbox_north) / 2, 50, 3000); |
foreach ($contents as $stop) { | foreach ($contents as $stop) { |
$description = 'http://bus.lambdacomplex.org/' . 'stop.php?stopid=' . $stop['stop_id'] . " <br>"; | $description = 'http://bus.lambdacomplex.org/' . 'stop.php?stopid=' . $stop['stop_id'] . " <br>"; |
$trips = getStopTripsWithTimes($stop['stop_id'], "", "", "", 3); | $trips = getStopTripsWithTimes($stop['stop_id'], "", "", "", 3); |
if ($trips) { | if ($trips) { |
foreach ($trips as $key => $row) { | foreach ($trips as $key => $row) { |
if ($key < 3) { | if ($key < 3) { |
$destination = getTripDestination($row['trip_id']); | $destination = getTripDestination($row['trip_id']); |
$description .= $row['route_short_name'] . ' ' . $destination['stop_name'] . ' @ ' . $row['arrival_time'] . "<br>"; | $description .= $row['route_short_name'] . ' ' . $destination['stop_name'] . ' @ ' . $row['arrival_time'] . "<br>"; |
} | } |
} | } |
} else { | } else { |
$description .= "No more trips today"; | $description .= "No more trips today"; |
} | } |
// Creates a Placemark and append it to the Document. | // Creates a Placemark and append it to the Document. |
$node = $dom->createElement('Placemark'); | $node = $dom->createElement('Placemark'); |
$placeNode = $docNode->appendChild($node); | $placeNode = $docNode->appendChild($node); |
// Creates an id attribute and assign it the value of id column. | // Creates an id attribute and assign it the value of id column. |
$placeNode->setAttribute('id', 'placemark' . $stop['stop_id']); | $placeNode->setAttribute('id', 'placemark' . $stop['stop_id']); |
// Create name, and description elements and assigns them the values of the name and address columns from the results. | // Create name, and description elements and assigns them the values of the name and address columns from the results. |
$nameNode = $dom->createElement('name', htmlentities($stop['stop_name'])); | $nameNode = $dom->createElement('name', htmlentities($stop['stop_name'])); |
$descriptionNode = $dom->createElement('description', $description); | $descriptionNode = $dom->createElement('description', $description); |
$placeNode->appendChild($nameNode); | $placeNode->appendChild($nameNode); |
$placeNode->appendChild($descriptionNode); | $placeNode->appendChild($descriptionNode); |
// Creates a Point element. | // Creates a Point element. |
$pointNode = $dom->createElement('Point'); | $pointNode = $dom->createElement('Point'); |
$placeNode->appendChild($pointNode); | $placeNode->appendChild($pointNode); |
// Creates a coordinates element and gives it the value of the lng and lat columns from the results. | // Creates a coordinates element and gives it the value of the lng and lat columns from the results. |
$coorStr = $stop['stop_lon'] . ',' . $stop['stop_lat']; | $coorStr = $stop['stop_lon'] . ',' . $stop['stop_lat']; |
$coorNode = $dom->createElement('coordinates', $coorStr); | $coorNode = $dom->createElement('coordinates', $coorStr); |
$pointNode->appendChild($coorNode); | $pointNode->appendChild($coorNode); |
} | } |
$kmlOutput = $dom->saveXML(); | $kmlOutput = $dom->saveXML(); |
echo $kmlOutput; | echo $kmlOutput; |
?> | ?> |
<?php | <?php |
/* | /* |
*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 |
*/ | */ |
define('PI2', 2*M_PI); | define('PI2', 2*M_PI); |
class HeatMapPoint{ | class HeatMapPoint{ |
public $x,$y; | public $x,$y; |
function __construct($x,$y) { | function __construct($x,$y) { |
$this->x = $x; | $this->x = $x; |
$this->y = $y; | $this->y = $y; |
} | } |
function __toString() { | function __toString() { |
return "({$this->x},{$this->y})"; | return "({$this->x},{$this->y})"; |
} | } |
}//Point | }//Point |
class HeatMap{ | class HeatMap{ |
//TRANSPARENCY | //TRANSPARENCY |
public static $WITH_ALPHA = 0; | public static $WITH_ALPHA = 0; |
public static $WITH_TRANSPARENCY = 1; | public static $WITH_TRANSPARENCY = 1; |
//GRADIENT STYLE | //GRADIENT STYLE |
public static $GRADIENT_CLASSIC = 'classic'; | public static $GRADIENT_CLASSIC = 'classic'; |
public static $GRADIENT_FIRE = 'fire'; | public static $GRADIENT_FIRE = 'fire'; |
public static $GRADIENT_PGAITCH = 'pgaitch'; | public static $GRADIENT_PGAITCH = 'pgaitch'; |
//GRADIENT MODE (for heatImage) | //GRADIENT MODE (for heatImage) |
public static $GRADIENT_NO_NEGATE_NO_INTERPOLATE = 0; | public static $GRADIENT_NO_NEGATE_NO_INTERPOLATE = 0; |
public static $GRADIENT_NO_NEGATE_INTERPOLATE = 1; | public static $GRADIENT_NO_NEGATE_INTERPOLATE = 1; |
public static $GRADIENT_NEGATE_NO_INTERPOLATE = 2; | public static $GRADIENT_NEGATE_NO_INTERPOLATE = 2; |
public static $GRADIENT_NEGATE_INTERPOLATE = 3; | public static $GRADIENT_NEGATE_INTERPOLATE = 3; |
//NOT PROCESSED PIXEL (for heatImage) | //NOT PROCESSED PIXEL (for heatImage) |
public static $KEEP_VALUE = 0; | public static $KEEP_VALUE = 0; |
public static $NO_KEEP_VALUE = 1; | public static $NO_KEEP_VALUE = 1; |
//CONSTRAINTS | //CONSTRAINTS |
private static $MIN_RADIUS = 2;//in px | private static $MIN_RADIUS = 2;//in px |
private static $MAX_RADIUS = 50;//in px | private static $MAX_RADIUS = 50;//in px |
private static $MAX_IMAGE_SIZE = 10000;//in px | private static $MAX_IMAGE_SIZE = 10000;//in px |
//generate an $image_width by $image_height pixels heatmap image of $points | //generate an $image_width by $image_height pixels heatmap image of $points |
public static function createImage($data, $image_width, $image_height, $mode=0, $spot_radius = 30, $dimming = 75, $gradient_name = 'classic'){ | public static function createImage($data, $image_width, $image_height, $mode=0, $spot_radius = 30, $dimming = 75, $gradient_name = 'classic'){ |
$_gradient_name = $gradient_name; | $_gradient_name = $gradient_name; |
if(($_gradient_name != self::$GRADIENT_CLASSIC) && ($_gradient_name != self::$GRADIENT_FIRE) && ($_gradient_name != self::$GRADIENT_PGAITCH)){ | if(($_gradient_name != self::$GRADIENT_CLASSIC) && ($_gradient_name != self::$GRADIENT_FIRE) && ($_gradient_name != self::$GRADIENT_PGAITCH)){ |
$_gradient_name = self::$GRADIENT_CLASSIC; | $_gradient_name = self::$GRADIENT_CLASSIC; |
} | } |
$_image_width = min(self::$MAX_IMAGE_SIZE, max(0, intval($image_width))); | $_image_width = min(self::$MAX_IMAGE_SIZE, max(0, intval($image_width))); |
$_image_height = min(self::$MAX_IMAGE_SIZE, max(0, intval($image_height))); | $_image_height = min(self::$MAX_IMAGE_SIZE, max(0, intval($image_height))); |
$_spot_radius = min(self::$MAX_RADIUS, max(self::$MIN_RADIUS, intval($spot_radius))); | $_spot_radius = min(self::$MAX_RADIUS, max(self::$MIN_RADIUS, intval($spot_radius))); |
$_dimming = min(255, max(0, intval($dimming))); | $_dimming = min(255, max(0, intval($dimming))); |
if(!is_array($data)){ | if(!is_array($data)){ |
return false; | return false; |
} | } |
$im = imagecreatetruecolor($_image_width, $_image_height); | $im = imagecreatetruecolor($_image_width, $_image_height); |
$white = imagecolorallocate($im, 255, 255, 255); | $white = imagecolorallocate($im, 255, 255, 255); |
imagefill($im, 0, 0, $white); | imagefill($im, 0, 0, $white); |
if(self::$WITH_ALPHA == $mode){ | if(self::$WITH_ALPHA == $mode){ |
imagealphablending($im, false); | imagealphablending($im, false); |
imagesavealpha($im,true); | imagesavealpha($im,true); |
} | } |
//Step 1: create grayscale image | //Step 1: create grayscale image |
foreach($data as $datum){ | foreach($data as $datum){ |
if( (is_array($datum) && (count($datum)==1)) || (!is_array($datum) && ('HeatMapPoint' == get_class($datum)))){//Plot points | if( (is_array($datum) && (count($datum)==1)) || (!is_array($datum) && ('HeatMapPoint' == get_class($datum)))){//Plot points |
if('HeatMapPoint' != get_class($datum)){ | if('HeatMapPoint' != get_class($datum)){ |
$datum = $datum[0]; | $datum = $datum[0]; |
} | } |
self::_drawCircularGradient($im, $datum->x, $datum->y, $_spot_radius, $_dimming); | self::_drawCircularGradient($im, $datum->x, $datum->y, $_spot_radius, $_dimming); |
}else if(is_array($datum)){//Draw lines | }else if(is_array($datum)){//Draw lines |
$length = count($datum)-1; | $length = count($datum)-1; |
for($i=0; $i < $length; ++$i){//Loop through points | for($i=0; $i < $length; ++$i){//Loop through points |
//Bresenham's algorithm to plot from from $datum[$i] to $datum[$i+1]; | //Bresenham's algorithm to plot from from $datum[$i] to $datum[$i+1]; |
self::_drawBilinearGradient($im, $datum[$i], $datum[$i+1], $_spot_radius, $_dimming); | self::_drawBilinearGradient($im, $datum[$i], $datum[$i+1], $_spot_radius, $_dimming); |
} | } |
} | } |
} | } |
//Gaussian filter | //Gaussian filter |
if($_spot_radius >= 30){ | if($_spot_radius >= 30){ |
imagefilter($im, IMG_FILTER_GAUSSIAN_BLUR); | imagefilter($im, IMG_FILTER_GAUSSIAN_BLUR); |
} | } |
//Step 2: create colored image | //Step 2: create colored image |
if(FALSE === ($grad_rgba = self::_createGradient($im, $mode, $_gradient_name))){ | if(FALSE === ($grad_rgba = self::_createGradient($im, $mode, $_gradient_name))){ |
return FALSE; | return FALSE; |
} | } |
$grad_size = count($grad_rgba); | $grad_size = count($grad_rgba); |
for($x=0; $x <$_image_width; ++$x){ | for($x=0; $x <$_image_width; ++$x){ |
for($y=0; $y <$_image_height; ++$y){ | for($y=0; $y <$_image_height; ++$y){ |
$level = imagecolorat($im, $x, $y) & 0xFF; | $level = imagecolorat($im, $x, $y) & 0xFF; |
if( ($level >= 0) && ($level < $grad_size) ){ | if( ($level >= 0) && ($level < $grad_size) ){ |
imagesetpixel($im, $x, $y, $grad_rgba[imagecolorat($im, $x, $y) & 0xFF]); | imagesetpixel($im, $x, $y, $grad_rgba[imagecolorat($im, $x, $y) & 0xFF]); |
} | } |
} | } |
} | } |
if(self::$WITH_TRANSPARENCY == $mode){ | if(self::$WITH_TRANSPARENCY == $mode){ |
imagecolortransparent($im, $grad_rgba[count($grad_rgba)-1]); | imagecolortransparent($im, $grad_rgba[count($grad_rgba)-1]); |
} | } |
return $im; | return $im; |
}//createImage | }//createImage |
//Heat an image | //Heat an image |
public static function heatImage($filepath, $gradient_name = 'classic', $mode= 0, $min_level=0, $max_level=255, $gradient_interpolate=0, $keep_value=0){ | public static function heatImage($filepath, $gradient_name = 'classic', $mode= 0, $min_level=0, $max_level=255, $gradient_interpolate=0, $keep_value=0){ |
$_gradient_name = $gradient_name; | $_gradient_name = $gradient_name; |
if(($_gradient_name != self::$GRADIENT_CLASSIC) && ($_gradient_name != self::$GRADIENT_FIRE) && ($_gradient_name != self::$GRADIENT_PGAITCH)){ | if(($_gradient_name != self::$GRADIENT_CLASSIC) && ($_gradient_name != self::$GRADIENT_FIRE) && ($_gradient_name != self::$GRADIENT_PGAITCH)){ |
$_gradient_name = self::$GRADIENT_CLASSIC; | $_gradient_name = self::$GRADIENT_CLASSIC; |
} | } |
$_min_level = min(255, max(0, intval($min_level))); | $_min_level = min(255, max(0, intval($min_level))); |
$_max_level = min(255, max(0, intval($max_level))); | $_max_level = min(255, max(0, intval($max_level))); |
//try opening jpg first then png then gif format | //try opening jpg first then png then gif format |
if(FALSE === ($im = @imagecreatefromjpeg($filepath))){ | if(FALSE === ($im = @imagecreatefromjpeg($filepath))){ |
if(FALSE === ($im = @imagecreatefrompng($filepath))){ | if(FALSE === ($im = @imagecreatefrompng($filepath))){ |
if(FALSE === ($im = @imagecreatefromgif($filepath))){ | if(FALSE === ($im = @imagecreatefromgif($filepath))){ |
return FALSE; | return FALSE; |
} | } |
} | } |
} | } |
if(self::$WITH_ALPHA == $mode){ | if(self::$WITH_ALPHA == $mode){ |
imagealphablending($im, false); | imagealphablending($im, false); |
imagesavealpha($im,true); | imagesavealpha($im,true); |
} | } |
$width = imagesx($im); | $width = imagesx($im); |
$height = imagesy($im); | $height = imagesy($im); |
if(FALSE === ($grad_rgba = self::_createGradient($im, $mode, $_gradient_name))){ | if(FALSE === ($grad_rgba = self::_createGradient($im, $mode, $_gradient_name))){ |
return FALSE; | return FALSE; |
} | } |
//Convert to grayscale | //Convert to grayscale |
$grad_size = count($grad_rgba); | $grad_size = count($grad_rgba); |
$level_range = $_max_level - $_min_level; | $level_range = $_max_level - $_min_level; |
for($x=0; $x <$width; ++$x){ | for($x=0; $x <$width; ++$x){ |
for($y=0; $y <$height; ++$y){ | for($y=0; $y <$height; ++$y){ |
$rgb = imagecolorat($im, $x, $y); | $rgb = imagecolorat($im, $x, $y); |
$r = ($rgb >> 16) & 0xFF; | $r = ($rgb >> 16) & 0xFF; |
$g = ($rgb >> 8) & 0xFF; | $g = ($rgb >> 8) & 0xFF; |
$b = $rgb & 0xFF; | $b = $rgb & 0xFF; |
$gray_level = Min(255, Max(0, floor(0.33 * $r + 0.5 * $g + 0.16 * $b)));//between 0 and 255 | $gray_level = Min(255, Max(0, floor(0.33 * $r + 0.5 * $g + 0.16 * $b)));//between 0 and 255 |
if( ($gray_level >= $_min_level) && ($gray_level <= $_max_level) ){ | if( ($gray_level >= $_min_level) && ($gray_level <= $_max_level) ){ |
switch($gradient_interpolate){ | switch($gradient_interpolate){ |
case self::$GRADIENT_NO_NEGATE_NO_INTERPOLATE: | case self::$GRADIENT_NO_NEGATE_NO_INTERPOLATE: |
//$_max_level takes related lowest gradient color | //$_max_level takes related lowest gradient color |
//$_min_level takes related highest gradient color | //$_min_level takes related highest gradient color |
$value = 255 - $gray_level; | $value = 255 - $gray_level; |
break; | break; |
case self::$GRADIENT_NEGATE_NO_INTERPOLATE: | case self::$GRADIENT_NEGATE_NO_INTERPOLATE: |
//$_max_level takes related highest gradient color | //$_max_level takes related highest gradient color |
//$_min_level takes related lowest gradient color | //$_min_level takes related lowest gradient color |
$value = $gray_level; | $value = $gray_level; |
break; | break; |
case self::$GRADIENT_NO_NEGATE_INTERPOLATE: | case self::$GRADIENT_NO_NEGATE_INTERPOLATE: |
//$_max_level takes lowest gradient color | //$_max_level takes lowest gradient color |
//$_min_level takes highest gradient color | //$_min_level takes highest gradient color |
$value = 255- floor(($gray_level - $_min_level) * $grad_size / $level_range); | $value = 255- floor(($gray_level - $_min_level) * $grad_size / $level_range); |
break; | break; |
case self::$GRADIENT_NEGATE_INTERPOLATE: | case self::$GRADIENT_NEGATE_INTERPOLATE: |
//$_max_level takes highest gradient color | //$_max_level takes highest gradient color |
//$_min_level takes lowest gradient color | //$_min_level takes lowest gradient color |
$value = floor(($gray_level - $_min_level) * $grad_size / $level_range); | $value = floor(($gray_level - $_min_level) * $grad_size / $level_range); |
break; | break; |
default: | default: |
} | } |
imagesetpixel($im, $x, $y, $grad_rgba[$value]); | imagesetpixel($im, $x, $y, $grad_rgba[$value]); |
}else{ | }else{ |
if(self::$KEEP_VALUE == $keep_value){ | if(self::$KEEP_VALUE == $keep_value){ |
//Do nothing | //Do nothing |
}else{//self::$NO_KEEP_VALUE | }else{//self::$NO_KEEP_VALUE |
imagesetpixel($im, $x, $y, imagecolorallocatealpha($im,0,0,0,0)); | imagesetpixel($im, $x, $y, imagecolorallocatealpha($im,0,0,0,0)); |
} | } |
} | } |
} | } |
} | } |
if(self::$WITH_TRANSPARENCY == $mode){ | if(self::$WITH_TRANSPARENCY == $mode){ |
imagecolortransparent($im, $grad_rgba[count($grad_rgba)-1]); | imagecolortransparent($im, $grad_rgba[count($grad_rgba)-1]); |
} | } |
return $im; | return $im; |
}//heatImage | }//heatImage |
private static function _drawCircularGradient(&$im, $center_x, $center_y, $spot_radius, $dimming){ | private static function _drawCircularGradient(&$im, $center_x, $center_y, $spot_radius, $dimming){ |
$dirty = array(); | $dirty = array(); |
$ratio = (255 - $dimming) / $spot_radius; | $ratio = (255 - $dimming) / $spot_radius; |
for($r=$spot_radius; $r > 0; --$r){ | for($r=$spot_radius; $r > 0; --$r){ |
$channel = $dimming + $r * $ratio; | $channel = $dimming + $r * $ratio; |
$angle_step = 0.45/$r; //0.01; | $angle_step = 0.45/$r; //0.01; |
//Process pixel by pixel to draw a radial grayscale radient | //Process pixel by pixel to draw a radial grayscale radient |
for($angle=0; $angle <= PI2; $angle += $angle_step){ | for($angle=0; $angle <= PI2; $angle += $angle_step){ |
$x = floor($center_x + $r*cos($angle)); | $x = floor($center_x + $r*cos($angle)); |
$y = floor($center_y + $r*sin($angle)); | $y = floor($center_y + $r*sin($angle)); |
if(!isset($dirty[$x][$y])){ | if(!isset($dirty[$x][$y])){ |
$previous_channel = @imagecolorat($im, $x, $y) & 0xFF;//grayscale so same value | $previous_channel = @imagecolorat($im, $x, $y) & 0xFF;//grayscale so same value |
$new_channel = Max(0, Min(255,($previous_channel * $channel)/255)); | $new_channel = Max(0, Min(255,($previous_channel * $channel)/255)); |
imagesetpixel($im, $x, $y, imagecolorallocate($im, $new_channel, $new_channel, $new_channel)); | imagesetpixel($im, $x, $y, imagecolorallocate($im, $new_channel, $new_channel, $new_channel)); |
$dirty[$x][$y] = 0; | $dirty[$x][$y] = 0; |
} | } |
} | } |
} | } |
}//_drawCircularGradient | }//_drawCircularGradient |
private static function _drawBilinearGradient(&$im, $point0, $point1, $spot_radius, $dimming){ | private static function _drawBilinearGradient(&$im, $point0, $point1, $spot_radius, $dimming){ |
if($point0->x < $point1->x){ | if($point0->x < $point1->x){ |
$x0 = $point0->x; | $x0 = $point0->x; |
$y0 = $point0->y; | $y0 = $point0->y; |
$x1 = $point1->x; | $x1 = $point1->x; |
$y1 = $point1->y; | $y1 = $point1->y; |
}else{ | }else{ |
$x0 = $point1->x; | $x0 = $point1->x; |
$y0 = $point1->y; | $y0 = $point1->y; |
$x1 = $point0->x; | $x1 = $point0->x; |
$y1 = $point0->y; | $y1 = $point0->y; |
} | } |
if( ($x0==$x1) && ($y0==$y1)){//check if same coordinates | if( ($x0==$x1) && ($y0==$y1)){//check if same coordinates |
return false; | return false; |
} | } |
$steep = (abs($y1 - $y0) > abs($x1 - $x0))? true: false; | $steep = (abs($y1 - $y0) > abs($x1 - $x0))? true: false; |
if($steep){ | if($steep){ |
list($x0, $y0) = array($y0, $x0);//swap | list($x0, $y0) = array($y0, $x0);//swap |
list($x1, $y1) = array($y1, $x1);//swap | list($x1, $y1) = array($y1, $x1);//swap |
} | } |
if($x0>$x1){ | if($x0>$x1){ |
list($x0, $x1) = array($x1, $x0);//swap | list($x0, $x1) = array($x1, $x0);//swap |
list($y0, $y1) = array($y1, $y0);//swap | list($y0, $y1) = array($y1, $y0);//swap |
} | } |
$deltax = $x1 - $x0; | $deltax = $x1 - $x0; |
$deltay = abs($y1 - $y0); | $deltay = abs($y1 - $y0); |
$error = $deltax / 2; | $error = $deltax / 2; |
$y = $y0; | $y = $y0; |
if( $y0 < $y1){ | if( $y0 < $y1){ |
$ystep = 1; | $ystep = 1; |
}else{ | }else{ |
$ystep = -1; | $ystep = -1; |
} | } |
$step = max(1, floor($spot_radius/ 3)); | $step = max(1, floor($spot_radius/ 3)); |
for($x=$x0; $x<=$x1; ++$x){//Loop through x value | for($x=$x0; $x<=$x1; ++$x){//Loop through x value |
if(0==(($x-$x0) % $step)){ | if(0==(($x-$x0) % $step)){ |
if($steep){ | if($steep){ |
self::_drawCircularGradient(&$im, $y, $x, $spot_radius, $dimming); | self::_drawCircularGradient($im, $y, $x, $spot_radius, $dimming); |
}else{ | }else{ |
self::_drawCircularGradient(&$im, $x, $y, $spot_radius, $dimming); | self::_drawCircularGradient($im, $x, $y, $spot_radius, $dimming); |
} | } |
} | } |
$error -= $deltay; | $error -= $deltay; |
if($error<0){ | if($error<0){ |
$y = $y + $ystep; | $y = $y + $ystep; |
$error = $error + $deltax; | $error = $error + $deltax; |
} | } |
} | } |
}//_drawBilinearGradient | }//_drawBilinearGradient |
private static function _createGradient($im, $mode, $gradient_name){ | private static function _createGradient($im, $mode, $gradient_name){ |
//create the gradient from an image | //create the gradient from an image |
if(FALSE === ($grad_im = imagecreatefrompng('gradient/'.$gradient_name.'.png'))){ | if(FALSE === ($grad_im = imagecreatefrompng('gradient/'.$gradient_name.'.png'))){ |
return FALSE; | return FALSE; |
} | } |
$width_g = imagesx($grad_im); | $width_g = imagesx($grad_im); |
$height_g = imagesy($grad_im); | $height_g = imagesy($grad_im); |
//Get colors along the longest dimension | //Get colors along the longest dimension |
//Max density is for lower channel value | //Max density is for lower channel value |
for($y=$height_g-1; $y >= 0 ; --$y){ | for($y=$height_g-1; $y >= 0 ; --$y){ |
$rgb = imagecolorat($grad_im, 1, $y); | $rgb = imagecolorat($grad_im, 1, $y); |
//Linear function | //Linear function |
$alpha = Min(127, Max(0, floor(127 - $y/2))); | $alpha = Min(127, Max(0, floor(127 - $y/2))); |
if(self::$WITH_ALPHA == $mode){ | if(self::$WITH_ALPHA == $mode){ |
$grad_rgba[] = imagecolorallocatealpha($im, ($rgb >> 16) & 0xFF, ($rgb >> 8) & 0xFF, $rgb & 0xFF, $alpha); | $grad_rgba[] = imagecolorallocatealpha($im, ($rgb >> 16) & 0xFF, ($rgb >> 8) & 0xFF, $rgb & 0xFF, $alpha); |
}else{ | }else{ |
$grad_rgba[] = imagecolorallocate($im, ($rgb >> 16) & 0xFF, ($rgb >> 8) & 0xFF, $rgb & 0xFF); | $grad_rgba[] = imagecolorallocate($im, ($rgb >> 16) & 0xFF, ($rgb >> 8) & 0xFF, $rgb & 0xFF); |
} | } |
} | } |
imagedestroy($grad_im); | imagedestroy($grad_im); |
unset($grad_im); | unset($grad_im); |
return($grad_rgba); | return($grad_rgba); |
}//_createGradient | }//_createGradient |
}//Heatmap | }//Heatmap |
?> | ?> |