Created
November 20, 2012 17:12
-
-
Save jaketoolson/4119324 to your computer and use it in GitHub Desktop.
Plotter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The above code is used to generate a dynamic image similar to below: | |
https://dl.dropbox.com/u/15302156/flows.png |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* for constructing GIS type images driven by latitude/longitude coordinates | |
* with some specialize power industry functions | |
* | |
* Image($x,$y) - constructs the image x width, y height | |
* show() - displays the image | |
* save($f_name) - save image as a png with file name $f_name | |
* destroy() - destroys the image and frees memory | |
* SetBackground($r,$g,$b) - set rgb overall background | |
* SetCenterColor($rcenter,$gcenter,$bcenter) - center color for a gradient circle | |
* AddGradientCircle($width,$xcenter,$ycenter) - adds a single gradient circle | |
* SetLineColor($r,$g,$b) - sets rgb color for lines | |
* SetTextColor($r,$g,$b) - sets rgb color for text | |
* SetFillColor($r,$g,$b) - fill color for fill operations | |
* AddCircle($lat,$lon,$diameter,$label,$fill="unfilled") - circle with optional text and optional fill | |
* AddFilledCircle($lat,$lon,$diameter) - adds a filled circle, no text, no outline | |
* AddLine($x1,$y1,$x2,$y2,$thick=1) | |
* AddRectangle($x1,$y1,$x2,$y2,$thick=1) - rectangle outline of given widht | |
* AddFilledRectangle($x1,$y1,$x2,$y2,$label) - filled rectange, no outline, optional text | |
* AddText($text,$fontsize,$angle,$x,$y,$alignment) - centered vertically on y, alignment at x (relative to text) | |
* AddArrowLine($lat1,$lon1,$lat2,$lon2,$flow) - for displaying power flows, negative flows allowed | |
* SetScale($zerolat,$zerolon,$maxlat,$maxlon) - scale for transforming lat/lon to x,y scale of image | |
* AddPolygonFile($file,$fill) - file of lat/lon points, $fill = "outline", "fill", or "both" | |
* AddLineFile($file,$thick=1) - file of lat/lon points defining a multisement line, SetLineColor to set color | |
* DMStoDEC($deg,$min,$sec) - convert to decimal form of lat or lon | |
* SetColorScale($min,$low,$high,$max) - color break points | |
* GetColor($p) - sets internal color variables for price/flow (coverted to a price) | |
* AddPriceCircle($lat,$lon,$name,$price) - adds a gradient circle and label at lat/lon | |
* AddLegend($x1,$y1,$fontsize,$alignment,$labels) - add legend block, upper left x1,y1, "right" or "left", array of labels | |
* AddImgMap($mname,) - sets up and adds the image map name also used for php file name | |
* FinishImgMap() - completes the image map string into GLOBALS ["$mapname"] | |
* | |
*/ | |
class Image{ | |
var $file_name; | |
var $info; | |
var $width; | |
var $height; | |
var $image; | |
var $org_image; | |
var $lata; // a & b scale factor for lat / long to point location | |
var $latb; | |
var $lona; | |
var $lonb; | |
var $linecolor; | |
var $textcolor; | |
var $fillcolor; // for filing polygons | |
var $backred; | |
var $backgreen; | |
var $backblue; | |
var $scale; // array with prices and colors | |
var $pricer; // for price being plotted the r value | |
var $priceg; | |
var $priceb; | |
var $font_file; | |
var $mapname; // name for image map variable and calls | |
var $mapstring; // the image map string | |
/** | |
* Constructor - | |
* Arguments : Image Filepath | |
*/ | |
function Image($x,$y) { | |
$this->image = @imagecreatetruecolor($x, $y); | |
$this->info['mime']="image/png"; | |
$this->width = $x; | |
$this->height = $y; | |
$this->org_image = $this->image; | |
$this->backred = 255; // white default | |
$this->backgreen = 255; | |
$this->backblue = 255; | |
$this->textcolor = imagecolorallocate($this->image,0,0,0); // black default | |
$this->linecolor = imagecolorallocate($this->image,0,0,0); | |
$this->fillcolor = imagecolorallocate($this->image,255,255,255); | |
$this->font_file="plot/NCS.ttf"; | |
} // end function | |
/** | |
* Display the image and then destroy it. | |
* Example: $img->show(); | |
*/ | |
function show() { | |
header("Content-type: ".$this->info['mime']); | |
imagepng($this->image); | |
} | |
/************************************************************* | |
* save the image | |
* use .png for now | |
*/ | |
function save($f_name) { | |
$this->file_name = $f_name; | |
return imagepng($this->image, $f_name); | |
} | |
/** | |
* Destroy the image to save the memory. Do this after all operations are complete. | |
*/ | |
function destroy() { | |
imagedestroy($this->image); | |
imagedestroy($this->org_image); | |
} | |
/** | |
* set up the image map | |
*/ | |
function AddImgMap($mname) { | |
$this->mapname = $mname; | |
$this->mapstring = "<div><map name=\"$this->mapname\" id=\"$this->mapname\">"; | |
} | |
/** | |
* finish the image map | |
*/ | |
function FinishImgMap() { | |
$this->mapstring .= "</map></div>"; | |
} | |
/** | |
* set background color of entire image | |
*/ | |
function SetBackground($r,$g,$b) { | |
$back_color = imagecolorallocate($this->image, $r,$g,$b); | |
imagefill($this->image, 0, 0, $back_color); | |
$this->backred = $r; | |
$this->backgreen = $g; | |
$this->backblue = $b; | |
} // end function | |
/** | |
* set color of gradient at the center of the circle | |
*/ | |
function SetCenterColor($rcenter,$gcenter,$bcenter) { | |
$this->rcenter = $rcenter; // scale factor applied to red (0 = no red) | |
$this->gcenter = $gcenter; // scale factor applied to green | |
$this->bcenter = $bcenter;// scale factor applied to blue | |
} // end function | |
/** | |
* plots a gradient fill circle | |
* blends from background color to center color | |
*/ | |
function AddGradientCircle($width, $xcenter, $ycenter) { | |
$kr= ($this->backred-$this->rcenter)*(2/$width); | |
$kg= ($this->backgreen-$this->gcenter)*(2/$width); | |
$kb= ($this->backblue-$this->bcenter)*(2/$width); | |
for ($i = 0.5; $i <= $width/2; $i++){ | |
$diameter = $width - 2 * $i; | |
$r = $this->backred - $i * $kr; | |
$g = $this->backgreen - $i * $kg; | |
$b = $this->backblue - $i * $kb; | |
$color = imagecolorallocate($this->image, $r, $g, $b); | |
imagearc($this->image, $xcenter, $ycenter, $diameter, $diameter, 0, 360, $color); | |
imagefilltoborder($this->image, $xcenter, $ycenter, $color, $color); | |
} | |
} // end function | |
/** | |
* set color for lines | |
*/ | |
function SetLineColor($r,$g,$b) { | |
$this->linecolor = imagecolorallocate($this->image, $r,$g,$b); | |
} // end function | |
/** | |
* set color for text | |
*/ | |
function SetTextColor($r,$g,$b) { | |
$this->textcolor = imagecolorallocate($this->image, $r,$g,$b); | |
} // end function | |
/** | |
* set polygon/circle/rectangle fill color | |
*/ | |
function SetFillColor($r,$g,$b) { | |
$this->fillcolor = imagecolorallocate($this->image, $r,$g,$b); | |
} // end function | |
/** | |
* add a filled/unfilled circle with optional text | |
*/ | |
function AddCircle($lat,$lon,$diameter,$label,$fill,$mapit,$id,$title) { | |
// *** convert lat, lon into xy coordinates | |
if(stripos($lat,'+')) { // deg, min, sec format | |
list($d,$m,$s) = explode("+",$lat); | |
$ycenter = round($this->DMStoDEC($d,$m,$s)*$this->lata +$this->latb); | |
list($d,$m,$s) = explode("+",$lon); | |
$xcenter = round($this->DMStoDEC($d,$m,$s)*$this->lona +$this->lonb); | |
} else { // decimal format | |
$ycenter = round($lat*$this->lata +$this->latb); | |
$xcenter = round(abs($lon)*$this->lona +$this->lonb); | |
} | |
imagearc($this->image, $xcenter, $ycenter, $diameter, $diameter, 0, 360, $this->linecolor); | |
if ($fill=="filled") { | |
imagefilltoborder($this->image, $xcenter, $ycenter, $this->linecolor, $this->fillcolor); | |
} | |
// *** now the text labels if non-null string passed in | |
if ($label<>"filled") { | |
$t = $label; | |
$bbox= imageftbbox ( 8, 0, $this->font_file, $t); | |
$bwidth = abs($bbox[4] - $bbox[0]); | |
$bheight = abs($bbox[1] - $bbox[5]); | |
$txc=$xcenter-$bwidth/2; | |
$tyc=$ycenter+$bheight/2; // seems better without correction -$bheight/2; | |
imagefttext($this->image, 8, 0, $txc, $tyc, $this->textcolor, $this->font_file,$t); | |
} | |
if ($mapit>0){ | |
$this->mapstring .= " <area shape=\"circle\" coords = \"$xcenter, $ycenter, $mapit\" href=\"$this->mapname.php?wxcode=$id\" title=\"$title\" target = \"_self\" /> "; | |
} | |
} // end function | |
/** | |
* add a filled circle - no text no outline | |
*/ | |
function AddFilledCircle($lat,$lon,$diameter) { | |
// *** convert lat, lon into xy coordinates | |
if(stripos($lat,'+')) { // deg, min, sec format | |
list($d,$m,$s) = explode("+",$lat); | |
$ycenter = round($this->DMStoDEC($d,$m,$s)*$this->lata +$this->latb); | |
list($d,$m,$s) = explode("+",$lon); | |
$xcenter = round($this->DMStoDEC($d,$m,$s)*$this->lona +$this->lonb); | |
} else { // decimal format | |
$ycenter = round($lat*$this->lata +$this->latb); | |
$xcenter = round(abs($lon)*$this->lona +$this->lonb); | |
} | |
imagefilledellipse($this->image, $xcenter, $ycenter, $diameter, $diameter,$this->fillcolor); | |
} // end function | |
/** | |
* add a line | |
*/ | |
function AddLine($x1,$y1,$x2,$y2,$thick=1) { | |
$x1 = round($x1); | |
$y1 = round($y1); | |
$x2 = round($x2); | |
$y2 = round($y2); | |
imagesetthickness($this->image, $thick); | |
imageline($this->image,$x1,$y1,$x2,$y2,$this->linecolor); | |
imagesetthickness($this->image, 1); | |
} // end function | |
/** | |
* add a rectangle | |
*/ | |
function AddRectangle($x1,$y1,$x2,$y2,$thick=1) { | |
imagesetthickness($this->image, $thick); | |
imagerectangle($this->image,$x1,$y1,$x2,$y2,$this->linecolor); | |
imagesetthickness($this->image, 1); | |
} // end function | |
/** | |
* add a filled rectangle with optional text | |
*/ | |
function AddFilledRectangle($x1,$y1,$x2,$y2,$label) { | |
imagefilledrectangle($this->image, $x1, $y1, $x2,$y2,$this->fillcolor); | |
if ($label<>"") { | |
$xcenter = ($x1+$x2)/2; | |
$ycenter = ($y1+$y2)/2; | |
$t = $label; | |
$bbox= imageftbbox ( 8, 0, $this->font_file, $t); | |
$bwidth = abs($bbox[4] - $bbox[0]); | |
$bheight = abs($bbox[1] - $bbox[5]); | |
$txc=$xcenter-$bwidth/2; | |
$tyc=$ycenter+$bheight/2; // seems better without correction -$bheight/2; | |
imagefttext($this->image, 8, 0, $txc, $tyc, $this->textcolor, $this->font_file,$t); | |
} | |
} // end function | |
/** | |
* add text with params for size, angle (0 or 90), location, and alignment | |
*/ | |
function AddText($text,$fontsize,$angle,$x,$y,$alignment) { | |
$bbox= imageftbbox ( $fontsize, $angle, $this->font_file, $text); | |
$bwidth = abs($bbox[4] - $bbox[0]); | |
$bheight = abs($bbox[1] - $bbox[5]); | |
if($angle==0) { | |
if ($alignment == "center"){ | |
$xt=$x-$bwidth/2; | |
$yt=$y+$bheight/2; | |
} | |
if ($alignment == "left"){ | |
$xt=$x; | |
$yt=$y+bheight/2; | |
} | |
if ($alignment == "right"){ | |
$xt=$x-$bwidth; | |
$yt=$y+bheight/2; | |
} | |
} else { | |
// 90 degrees | |
if ($alignment == "center"){ | |
$xt=$x-$bwidth/2; | |
$yt=$y+$bheight/2; | |
} | |
if ($alignment == "left"){ | |
$xt=$x-$bwidth/2; | |
$yt=$y; | |
} | |
if ($alignment == "right"){ | |
$xt=$x-$bwidth/2; | |
$yt=$y+$bheight; | |
} | |
} | |
imagefttext($this->image, $fontsize, $angle, $xt, $yt, $this->textcolor, $this->font_file,$text); | |
} // end function | |
/** | |
* add a legend to the image image | |
*/ | |
function AddLegend($x1,$y1,$fontsize,$alignment,$label) { | |
$legend_count=count($label); | |
$bwidth=0; | |
for ($i=0;$i<$legend_count;$i++) { | |
$bbox= imageftbbox ( $fontsize, 0, $this->font_file, $label[$i]); | |
$bwidth = max($bwidth,abs($bbox[4] - $bbox[0])); | |
} | |
// *** alignment | |
if($alignment=="left") { | |
$x2 = $x1 + $bwidth + 4*$fontsize; | |
$y2 = $y1 + (2*($legend_count)+1)*$fontsize; | |
} else { // right | |
$x2 = $x1; | |
$x1 = $x2 -($bwidth + 4*$fontsize); | |
$y2 = $y1 + (2*($legend_count)+1)*$fontsize; | |
} | |
$text = ""; | |
$this->AddFilledRectangle($x1,$y1,$x2,$y2,$text); | |
$this->AddRectangle($x1,$y1,$x2,$y2,$thick=1); | |
for ($i=0;$i<$legend_count;$i++) { | |
$this->AddText($label[$i],$fontsize,0,$x1+2*$fontsize,$y1+2*($i+1)*$fontsize,"left"); | |
} | |
} // end function | |
/** | |
* add a line with sized arrow | |
* file data looks like -> 41+59+07,124+12+28 (lat, lon) | |
*/ | |
function AddArrowLine($lat1,$lon1,$lat2,$lon2,$flow,$flow_scale=10000) { | |
$size = ($this->height+$this->width)/2; | |
// $arrowmax = .1; | |
$arrowmax = .07; | |
$arrow_size = min($arrowmax*$size,6+abs(($flow/$flow_scale)*$size*$arrowmax)); | |
$arrow_color = abs(250*($flow/$flow_scale)); | |
// *** convert lat, lon into xy coordinates | |
if(stripos($lat1,'+')) { // deg, min, sec format | |
list($d,$m,$s) = explode("+",$lat1); | |
$y1 = round($this->DMStoDEC($d,$m,$s)*$this->lata +$this->latb); | |
list($d,$m,$s) = explode("+",$lon1); | |
$x1 = round($this->DMStoDEC($d,$m,$s)*$this->lona +$this->lonb); | |
} else { // decimal format | |
$y1 = round($lat1*$this->lata +$this->latb); | |
$x1 = round(abs($lon1)*$this->lona +$this->lonb); | |
} | |
if(stripos($lat2,'+')) { // deg, min, sec format | |
list($d,$m,$s) = explode("+",$lat2); | |
$y2 = round($this->DMStoDEC($d,$m,$s)*$this->lata +$this->latb); | |
list($d,$m,$s) = explode("+",$lon2); | |
$x2 = round($this->DMStoDEC($d,$m,$s)*$this->lona +$this->lonb); | |
} else { // decimal format | |
$y2 = round($lat2*$this->lata +$this->latb); | |
$x2 = round(abs($lon2)*$this->lona +$this->lonb); | |
} | |
// *** add the line | |
$this->AddLine($x1,$y1,$x2,$y2,1); | |
// *** adjust line angle for flow direction | |
if ($flow > 0) { | |
$angle = atan2($y2-$y1,$x2-$x1); | |
} else if ($flow <0) { | |
$angle = atan2($y2-$y1,$x2-$x1)+deg2rad(180); | |
} else { | |
return $flow; | |
} | |
// *** compute the arrow points | |
$aminus90 = $angle - deg2rad(90); | |
$aplus90 = $angle + deg2rad(90); | |
$sqrt3 = sqrt(3); | |
// ** arrow mid point | |
$mpx = round(($x1 + $x2)/2); | |
$mpy = round(($y1 + $y2)/2); | |
// ** middle of base | |
$bx = $mpx - cos($angle)*$arrow_size/2; | |
$by = $mpy - sin($angle)*$arrow_size/2; | |
// ** point of arrow | |
$px = $mpx + cos($angle)*$arrow_size/2; | |
$py = $mpy + sin($angle)*$arrow_size/2; | |
// ** left point | |
$lpx = $bx + cos($aminus90)*$arrow_size/$sqrt3; | |
$lpy = $by + sin($aminus90)*$arrow_size/$sqrt3; | |
// ** right point | |
$rpx = $bx + cos($aplus90)*$arrow_size/$sqrt3; | |
$rpy = $by + sin($aplus90)*$arrow_size/$sqrt3; | |
$points = array ($px,$py,$lpx,$lpy,$rpx,$rpy); | |
$num_points = 3; | |
// *** get a fill color for the arrow | |
$this->GetColor($arrow_color); | |
$frac = .8; // sets background at a washed out version of the price color | |
$r = 255-$frac*(255-$this->pricer); | |
$g = 255-$frac*(255-$this->priceg); | |
$b = 255-$frac*(255-$this->priceb); | |
$this->SetFillColor($r,$g,$b); | |
// *** add the arrow | |
imagefilledpolygon ( $this->image,$points,$num_points,$this->fillcolor ); | |
// *** now the label at upper rightmost point | |
if ($size >600 ) { | |
$font = 8; | |
} else { | |
$font = 7; | |
} | |
$font = 7; | |
if (($py>$lpy) and ($py>$rpy)) { | |
// must be either lp or rp | |
if ($lpx > $rpx) { | |
// lp is the one | |
$tx = $lpx; | |
$ty = $lpy; | |
} | |
if ($rpx > $lpx) { | |
// rp is the one | |
$tx = $rpx; | |
$ty = $rpy; | |
} | |
} | |
if (($lpy>$py) and ($lpy>$rpy)) { | |
// must be p or rp | |
if ($px > $rpx) { | |
// p is the one | |
$tx = $px; | |
$ty = $py; | |
} | |
if ($rpx > $px) { | |
// rp is the one | |
$tx = $rpx; | |
$ty = $rpy; | |
} | |
} | |
if (($rpy>$py) and ($rpy>$lpy)) { | |
// must be p or lp | |
if ($px > $lpx) { | |
// p is the one | |
$tx = $px; | |
$ty = $py; | |
} | |
if ($lpx > $px) { | |
// lp is the one | |
$tx = $lpx; | |
$ty = $lpy; | |
} | |
} | |
$text = abs($flow); | |
imagefttext($this->image, $font, 0, $tx, $ty, $this->textcolor, $this->font_file,$text); | |
} // end function | |
/** | |
* compute longitude scale factors | |
* | |
* $zerolat - latitude at top left corner of image | |
* $zerolon - longitude at top left corner of image | |
* $maxlat - latitude at bottom right corner of image | |
* $maxlon - longitude at bottom right corner of image | |
*/ | |
function SetScale($zerolat,$zerolon,$maxlat,$maxlon) { | |
$this->lata = $this->height/($maxlat-$zerolat); | |
$this->latb = - $this->lata *$zerolat; | |
$this->lona = $this->width/($maxlon-$zerolon); | |
$this->lonb = - $this->lona *$zerolon; | |
} // end function | |
/** | |
* add a polygon from a file | |
* file data looks like -> 41+59+07,124+12+28 (lat, lon) | |
*/ | |
function AddPolygonFile($file,$fill) { | |
($fp = fopen("$file","r")) or die ("could not open $target, bummer"); | |
flock ($fp, LOCK_EX); | |
$p=0; | |
while (!feof($fp)) { | |
$line = fgets($fp); | |
list($lat,$lon)=explode(",",$line); | |
list($d,$m,$s) = explode("+",$lat); | |
$points[2*$p+1] = round($this->DMStoDEC($d,$m,$s)*$this->lata +$this->latb); | |
list($d,$m,$s) = explode("+",$lon); | |
$points[2*$p] = round($this->DMStoDEC($d,$m,$s)*$this->lona +$this->lonb); | |
$p = $p+1; | |
} | |
$num_points=$p; | |
flock ($fp, LOCK_UN); | |
fclose($fp); | |
if ($fill=="outline") { | |
imagepolygon($this->image,$points,$num_points,$this->linecolor); | |
} | |
if ($fill=="filled") { | |
imagefilledpolygon ( $this->image,$points,$num_points,$this->fillcolor ); | |
} | |
if ($fill=="both") { | |
imagefilledpolygon ( $this->image,$points,$num_points,$this->fillcolor ); | |
imagepolygon($this->image,$points,$num_points,$this->linecolor); | |
} | |
} // end function | |
/** | |
* add a multisegment line from a file | |
* file data looks like -> 41+59+07,124+12+28 (lat, lon) or decimal format | |
*/ | |
function AddLineFile($file,$thick=1) { | |
($fp = fopen("$file","r")) or die ("could not open $target, bummer"); | |
flock ($fp, LOCK_EX); | |
$p=0; | |
while (!feof($fp)) { | |
$line = fgets($fp); | |
list($lat,$lon)=explode(",",$line); | |
if(stripos($lat,'+')) { // deg, min, sec format | |
list($d,$m,$s) = explode("+",$lat); | |
$y[$p] = round($this->DMStoDEC($d,$m,$s)*$this->lata +$this->latb); | |
list($d,$m,$s) = explode("+",$lon); | |
$x[$p] = round($this->DMStoDEC($d,$m,$s)*$this->lona +$this->lonb); | |
} else { // decimal format | |
$y[$p] = round($lat*$this->lata +$this->latb); | |
$x[$p] = round(abs($lon)*$this->lona +$this->lonb); | |
} | |
// list($d,$m,$s) = explode("+",$lat); | |
// $y[$p] = round($this->DMStoDEC($d,$m,$s)*$this->lata +$this->latb); | |
// list($d,$m,$s) = explode("+",$lon); | |
// $x[$p] = round($this->DMStoDEC($d,$m,$s)*$this->lona +$this->lonb); | |
if($p>=1){ | |
$x1 = $x[$p-1]; | |
$y1 = $y[$p-1]; | |
$x2 = $x[$p]; | |
$y2 = $y[$p]; | |
// echo "$x1,$y1,$x2,$y2,$thick <br>"; | |
$this->Addline($x1,$y1,$x2,$y2,$thick); | |
} | |
$p = $p+1; | |
} | |
$num_points=$p; | |
flock ($fp, LOCK_UN); | |
fclose($fp); | |
} // end function | |
/** | |
* adds text to map based on lat/lon point | |
* file data looks like -> 41+59+07,124+12+28 (lat, lon) | |
* using AddText($text,$fontsize,$angle,$x,$y,$alignment) | |
*/ | |
function AddTextFile($file,$fontsize,$angle,$alignment) { | |
($fp = fopen("$file","r")) or die ("could not open $target, bummer"); | |
flock ($fp, LOCK_EX); | |
$p=0; | |
while (!feof($fp)) { | |
$line = fgets($fp); | |
list($lat,$lon,$text)=explode(",",$line); | |
list($d,$m,$s) = explode("+",$lat); | |
$y = round($this->DMStoDEC($d,$m,$s)*$this->lata +$this->latb); | |
list($d,$m,$s) = explode("+",$lon); | |
$x = round($this->DMStoDEC($d,$m,$s)*$this->lona +$this->lonb); | |
// echo "$file,$text,$fontsize,$angle,$x,$y,$alignment<br>"; | |
$this->AddText($text,$fontsize,$angle,$x,$y,$alignment); | |
$p = $p+1; | |
} | |
$num_points=$p; | |
flock ($fp, LOCK_UN); | |
fclose($fp); | |
} // end function | |
/** | |
* Converts DMS ( Degrees / minutes / seconds ) | |
* to decimal format longitude / latitude | |
*/ | |
function DMStoDEC($deg,$min,$sec) { | |
return $deg+((($min*60)+($sec))/3600); | |
} | |
/** | |
* | |
* fills array for scaling prices | |
* | |
*/ | |
function SetColorScale($min,$low,$high,$max) { | |
$this->scale = array("max" => array ( "p" => $max, | |
"r" => 255, | |
"g" => 0, | |
"b" => 0 | |
), | |
"high"=> array ( "p" => $high, | |
"r" => 255, | |
"g" => 0, | |
"b" => 255 | |
), | |
"low"=> array ( "p" => $low, | |
"r" => 0, | |
"g" => 255, | |
"b" => 255 | |
), | |
"min"=> array ( "p" => $min, | |
"r" => 0, | |
"g" => 255, | |
"b" => 0 | |
) | |
); | |
} // end function | |
/** | |
* | |
* gets colors for a price | |
* | |
*/ | |
function GetColor($p) { | |
if($p <= $this->scale["min"]["p"]) { | |
$this->pricer = $this->scale["min"]["r"]; | |
$this->priceg = $this->scale["min"]["g"]; | |
$this->priceb = $this->scale["min"]["b"]; | |
} else | |
if ($p <= $this->scale["low"]["p"] ){ | |
$f = ($p -$this->scale["min"]["p"])/ | |
($this->scale["low"]["p"]-$this->scale["min"]["p"]); | |
$this->pricer = $this->scale["min"]["r"] + | |
($this->scale["low"]["r"]-$this->scale["min"]["r"]) * $f; | |
$this->priceg = $this->scale["min"]["g"] + | |
($this->scale["low"]["g"]-$this->scale["min"]["g"]) * $f; | |
$this->priceb = $this->scale["min"]["b"] + | |
($this->scale["low"]["b"]-$this->scale["min"]["b"]) * $f; | |
} else | |
if ($p <= $this->scale["high"]["p"] ){ | |
$f = ($p -$this->scale["low"]["p"])/ | |
($this->scale["high"]["p"]-$this->scale["low"]["p"]); | |
$this->pricer = $this->scale["low"]["r"] + | |
($this->scale["high"]["r"]-$this->scale["low"]["r"]) * $f; | |
$this->priceg = $this->scale["low"]["g"] + | |
($this->scale["high"]["g"]-$this->scale["low"]["g"]) * $f; | |
$this->priceb = $this->scale["low"]["b"] + | |
($this->scale["high"]["b"]-$this->scale["low"]["b"]) * $f; | |
} else | |
if ($p <= $this->scale["max"]["p"] ){ | |
$f = ($p -$this->scale["high"]["p"])/ | |
($this->scale["max"]["p"]-$this->scale["high"]["p"]); | |
$this->pricer = $this->scale["high"]["r"] + | |
($this->scale["max"]["r"]-$this->scale["high"]["r"]) * $f; | |
$this->priceg = $this->scale["high"]["g"] + | |
($this->scale["max"]["g"]-$this->scale["high"]["g"]) * $f; | |
$this->priceb = $this->scale["high"]["b"] + | |
($this->scale["max"]["b"]-$this->scale["high"]["b"]) * $f; | |
} else { | |
$this->pricer = $this->scale["max"]["r"]; | |
$this->priceg = $this->scale["max"]["g"]; | |
$this->priceb = $this->scale["max"]["b"]; | |
} | |
} // end function | |
/** | |
* adds a gradient circle from a lat,lon,name, and price | |
* the lat/lon look like ->41+59+07,124+12+28 | |
*/ | |
function AddPriceCircle($lat,$lon,$name,$price,$hr) { | |
$maxfrac = .25; | |
$size = ($this->height+$this->width)/2; | |
$width = ($price/$this->scale["max"]["p"])*$maxfrac*$size; | |
$width = max(20,$width); // keep from being too small | |
$width = min($maxfrac*$size,$width); // keep from being too large | |
if(stripos($lat,'+')) { // deg, min, sec format | |
list($d,$m,$s) = explode("+",$lat); | |
$ycenter = round($this->DMStoDEC($d,$m,$s)*$this->lata +$this->latb); | |
list($d,$m,$s) = explode("+",$lon); | |
$xcenter = round($this->DMStoDEC($d,$m,$s)*$this->lona +$this->lonb); | |
} else { // decimal format | |
// echo "decimal<BR>"; | |
$ycenter = round($lat*$this->lata +$this->latb); | |
$xcenter = round(abs($lon)*$this->lona +$this->lonb); // - lat in west 180, may need to tweak in east 180 | |
} | |
// print "$xcenter, $ycenter<BR>"; | |
$this->GetColor($price); | |
$this->SetCenterColor($this->pricer,$this->priceg,$this->priceb); | |
$this->AddGradientCircle($width, $xcenter, $ycenter); | |
// *** now the text labels | |
$t = "$name: \$$price/MWh HR: $hr"; | |
$bbox= imageftbbox ( 8, 0, $this->font_file, $t); | |
$bwidth = abs($bbox[4] - $bbox[0]); | |
$bheight = abs($bbox[1] - $bbox[5]); | |
$txc=$xcenter-$bwidth/2; | |
$tyc=$ycenter; // seems better without correction -$bheight/2; | |
imagefttext($this->image, 8, 0, $txc, $tyc, $this->textcolor, $this->font_file,$t); | |
} // end function | |
} // end class |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment