* Encode an array of integers according to Google's Simple Encoding
* Scales to largest value in array if $max is not set, truncates lower bound if $min is set
* Does NOT set the 's:' prefix so it can be called when creating multiple data series
* @link http://code.google.com/apis/chart/formats.html#simple
* @param array $values
* @param integer $max
* @return string
* @author Marcus Bointon <marcus@synchromedia.co.uk>
*/
function googleSimpleEncode($values, $max = -1, $min = 0) {
$encoding = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$chartdata = '';
$rangemax = 61;
if ($max < 0) {
$max = max($values);
}
if ($max < max($values)) {
$max = max($values);
}
$range = $max - $min;
$scale = $rangemax / $range;
foreach ($values as $k => $v) {
if ($v - $min >= 0) {
$chartdata .= $encoding[floor(($v - $min) * $scale)];
} else {
$chartdata .= '_';
}
}
return $chartdata;
}
/**
* Encode an array of integers according to Google's Extended Encoding
* Scales to largest value in array if $max is not set, truncates lower bound if $min is set
* Does NOT set the 'e:' prefix so it can be called when creating multiple data series
* @link http://code.google.com/apis/chart/formats.html#extended
* @param array $values
* @param integer $max
* @param integer $min
* @return string
* @author Marcus Bointon <marcus@synchromedia.co.uk>
*/
function googleExtendedEncode($values, $max = -1, $min = 0) {
$encoding = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-.';
$rangemax = 4095;
$chartdata = '';
if ($max < 0) {
$max = max($values);
}
//If max is smaller than the largest value, it will go beyond range allowed by the encoding (0..4095)
if ($max < max($values)) {
$max = max($values);
}
$range = $max - $min;
$scale = $rangemax / $range;
foreach ($values as $k => $v){
if ($v >= $min && $v <= $max) {
$scaledvalue = ($v - $min) * $scale;
$chartdata .= $encoding[floor($scaledvalue / 64)].$encoding[$scaledvalue % 64];
} else {
$chartdata .= '__'; // Value out of max range;
}
}
return($chartdata);
}
/**
* Encode an array of one or more integer arrays into one of the Google Charts API formats
* @link http://code.google.com/apis/chart/formats.html
* @param array $valuearrays An array of data series arrays you want to plot
* @param string $encoding 's' or 'e' for simple or extended encoding respectively
* @param integer $max Maximum value to scale to (-1 for auto-scaling, the default)
* @param integer $min Minimum value to truncate to
* @param boolean $commonscaling Whether to use the same scale for all series, or calculate each one separately
* @return string
* @author Marcus Bointon <marcus@synchromedia.co.uk>
*/
function googleMultiEncode($valuearrays, $encoding = 's', $max = -1, $min = 0, $commonscale = true) {
if ($encoding != 'e') {
$encoding = 's';
}
$chartdata = "$encoding:";
//Check that max value is valid (if given, must be >= largest value)
$amax = maxInArrays($valuearrays);
if ($max > 0 and $amax > $max) {
$max = $amax;
}
if ($max < 0 and $commonscale) {
$max = $amax;
}
$charts = array();
foreach($valuearrays as $array) {
if ($encoding == 's') {
$charts[] = googleSimpleEncode($array, $max, $min);
} else {
$charts[] = googleExtendedEncode($array, $max, $min);
}
}
$chartdata .= implode(',', $charts);
return($chartdata);
}
/**
* Get the largest value in an array of integer arrays
* @param array $arrays
* @return integer
*/
function maxInArrays($arrays) {
$amax = -1;
foreach($arrays as $array) {
if ($amax < max($array)) {
$amax = max($array);
}
}
return $amax;
}
$max = maxInArrays($a);
$m = googleMultiEncode($a, 'e', -1, 0, true);
echo "http://chart.apis.google.com/chart?cht=lc&chxt=y&chs=400x280&chxr=0,0,$max&chd=$m\n";
$m = googleMultiEncode($a, 's', -1, 0, true);
echo "http://chart.apis.google.com/chart?cht=lc&chxt=y&chs=400x280&chxr=0,0,$max&chd=$m\n";
Try to guess which is simple and which is extended encoding!
As you can see there's no real difference between the encodings for low-res data like this, so now that it's so easy to switch between them, you can just pick which is the most appropriate, trading off resolution for URL length. The separate maxInArrays functions is useful to extract the max value in your series ready to drop into your axis value. Here's an example to show how the choice of encoding is completely independent of your value range:
$m = googleSimpleEncode($a);
$max = max($a);
echo "http://chart.apis.google.com/chart?cht=bvs&chxt=y&chbh=a&chs=200x100&chxr=0,0,$max&chd=s:$m\n";
Please leave a comment or trackback if you you find this useful or have any bug reports, suggestions or other comments.
Credit to Google for their JavaScript version that I started with, and Ben Dodson and Felipe Barone for their versions, and to Lorna Jane for her Genshi in Serendipity tip.
Trackbacks
Trackback specific URI for this entryComments
Display comments as (Linear | Threaded)


