summaryrefslogtreecommitdiff
path: root/html/jpgraph/jpgraph_plotband.php
diff options
context:
space:
mode:
Diffstat (limited to 'html/jpgraph/jpgraph_plotband.php')
-rw-r--r--html/jpgraph/jpgraph_plotband.php635
1 files changed, 635 insertions, 0 deletions
diff --git a/html/jpgraph/jpgraph_plotband.php b/html/jpgraph/jpgraph_plotband.php
new file mode 100644
index 0000000..b7aef75
--- /dev/null
+++ b/html/jpgraph/jpgraph_plotband.php
@@ -0,0 +1,635 @@
+<?php
+//=======================================================================
+// File: JPGRAPH_PLOTBAND.PHP
+// Description: PHP4 Graph Plotting library. Extension module.
+// Created: 2004-02-18
+// Ver: $Id: jpgraph_plotband.php 1106 2009-02-22 20:16:35Z ljp $
+//
+// Copyright (c) Asial Corporation. All rights reserved.
+//========================================================================
+
+// Constants for types of static bands in plot area
+define("BAND_RDIAG",1); // Right diagonal lines
+define("BAND_LDIAG",2); // Left diagonal lines
+define("BAND_SOLID",3); // Solid one color
+define("BAND_VLINE",4); // Vertical lines
+define("BAND_HLINE",5); // Horizontal lines
+define("BAND_3DPLANE",6); // "3D" Plane
+define("BAND_HVCROSS",7); // Vertical/Hor crosses
+define("BAND_DIAGCROSS",8); // Diagonal crosses
+
+
+// Utility class to hold coordinates for a rectangle
+class Rectangle {
+ public $x,$y,$w,$h;
+ public $xe, $ye;
+ function __construct($aX,$aY,$aWidth,$aHeight) {
+ $this->x=$aX;
+ $this->y=$aY;
+ $this->w=$aWidth;
+ $this->h=$aHeight;
+ $this->xe=$aX+$aWidth-1;
+ $this->ye=$aY+$aHeight-1;
+ }
+}
+
+//=====================================================================
+// Class RectPattern
+// Base class for pattern hierarchi that is used to display patterned
+// bands on the graph. Any subclass that doesn't override Stroke()
+// must at least implement method DoPattern($aImg) which is responsible
+// for drawing the pattern onto the graph.
+//=====================================================================
+class RectPattern {
+ protected $color;
+ protected $weight;
+ protected $rect=null;
+ protected $doframe=true;
+ protected $linespacing; // Line spacing in pixels
+ protected $iBackgroundColor=-1; // Default is no background fill
+
+ function __construct($aColor,$aWeight=1) {
+ $this->color = $aColor;
+ $this->weight = $aWeight;
+ }
+
+ function SetBackground($aBackgroundColor) {
+ $this->iBackgroundColor=$aBackgroundColor;
+ }
+
+ function SetPos($aRect) {
+ $this->rect = $aRect;
+ }
+
+ function ShowFrame($aShow=true) {
+ $this->doframe=$aShow;
+ }
+
+ function SetDensity($aDens) {
+ if( $aDens < 1 || $aDens > 100 )
+ JpGraphError::RaiseL(16001,$aDens);
+ //(" Desity for pattern must be between 1 and 100. (You tried $aDens)");
+ // 1% corresponds to linespacing=50
+ // 100 % corresponds to linespacing 1
+ $this->linespacing = floor(((100-$aDens)/100.0)*50)+1;
+
+ }
+
+ function Stroke($aImg) {
+ if( $this->rect == null )
+ JpGraphError::RaiseL(16002);
+ //(" No positions specified for pattern.");
+
+ if( !(is_numeric($this->iBackgroundColor) && $this->iBackgroundColor==-1) ) {
+ $aImg->SetColor($this->iBackgroundColor);
+ $aImg->FilledRectangle($this->rect->x,$this->rect->y,$this->rect->xe,$this->rect->ye);
+ }
+
+ $aImg->SetColor($this->color);
+ $aImg->SetLineWeight($this->weight);
+
+ // Virtual function implemented by subclass
+ $this->DoPattern($aImg);
+
+ // Frame around the pattern area
+ if( $this->doframe )
+ $aImg->Rectangle($this->rect->x,$this->rect->y,$this->rect->xe,$this->rect->ye);
+ }
+
+}
+
+
+//=====================================================================
+// Class RectPatternSolid
+// Implements a solid band
+//=====================================================================
+class RectPatternSolid extends RectPattern {
+
+ function __construct($aColor="black",$aWeight=1) {
+ parent::__construct($aColor,$aWeight);
+ }
+
+ function DoPattern($aImg) {
+ $aImg->SetColor($this->color);
+ $aImg->FilledRectangle($this->rect->x,$this->rect->y,
+ $this->rect->xe,$this->rect->ye);
+ }
+}
+
+//=====================================================================
+// Class RectPatternHor
+// Implements horizontal line pattern
+//=====================================================================
+class RectPatternHor extends RectPattern {
+
+ function __construct($aColor="black",$aWeight=1,$aLineSpacing=7) {
+ parent::__construct($aColor,$aWeight);
+ $this->linespacing = $aLineSpacing;
+ }
+
+ function DoPattern($aImg) {
+ $x0 = $this->rect->x;
+ $x1 = $this->rect->xe;
+ $y = $this->rect->y;
+ while( $y < $this->rect->ye ) {
+ $aImg->Line($x0,$y,$x1,$y);
+ $y += $this->linespacing;
+ }
+ }
+}
+
+//=====================================================================
+// Class RectPatternVert
+// Implements vertical line pattern
+//=====================================================================
+class RectPatternVert extends RectPattern {
+
+ function __construct($aColor="black",$aWeight=1,$aLineSpacing=7) {
+ parent::__construct($aColor,$aWeight);
+ $this->linespacing = $aLineSpacing;
+ }
+
+ //--------------------
+ // Private methods
+ //
+ function DoPattern($aImg) {
+ $x = $this->rect->x;
+ $y0 = $this->rect->y;
+ $y1 = $this->rect->ye;
+ while( $x < $this->rect->xe ) {
+ $aImg->Line($x,$y0,$x,$y1);
+ $x += $this->linespacing;
+ }
+ }
+}
+
+
+//=====================================================================
+// Class RectPatternRDiag
+// Implements right diagonal pattern
+//=====================================================================
+class RectPatternRDiag extends RectPattern {
+
+ function __construct($aColor="black",$aWeight=1,$aLineSpacing=12) {
+ parent::__construct($aColor,$aWeight);
+ $this->linespacing = $aLineSpacing;
+ }
+
+ function DoPattern($aImg) {
+ // --------------------
+ // | / / / / /|
+ // |/ / / / / |
+ // | / / / / |
+ // --------------------
+ $xe = $this->rect->xe;
+ $ye = $this->rect->ye;
+ $x0 = $this->rect->x + round($this->linespacing/2);
+ $y0 = $this->rect->y;
+ $x1 = $this->rect->x;
+ $y1 = $this->rect->y + round($this->linespacing/2);
+
+ while($x0<=$xe && $y1<=$ye) {
+ $aImg->Line($x0,$y0,$x1,$y1);
+ $x0 += $this->linespacing;
+ $y1 += $this->linespacing;
+ }
+
+ if( $xe-$x1 > $ye-$y0 ) {
+ // Width larger than height
+ $x1 = $this->rect->x + ($y1-$ye);
+ $y1 = $ye;
+ $y0 = $this->rect->y;
+ while( $x0 <= $xe ) {
+ $aImg->Line($x0,$y0,$x1,$y1);
+ $x0 += $this->linespacing;
+ $x1 += $this->linespacing;
+ }
+
+ $y0=$this->rect->y + ($x0-$xe);
+ $x0=$xe;
+ }
+ else {
+ // Height larger than width
+ $diff = $x0-$xe;
+ $y0 = $diff+$this->rect->y;
+ $x0 = $xe;
+ $x1 = $this->rect->x;
+ while( $y1 <= $ye ) {
+ $aImg->Line($x0,$y0,$x1,$y1);
+ $y1 += $this->linespacing;
+ $y0 += $this->linespacing;
+ }
+
+ $diff = $y1-$ye;
+ $y1 = $ye;
+ $x1 = $diff + $this->rect->x;
+ }
+
+ while( $y0 <= $ye ) {
+ $aImg->Line($x0,$y0,$x1,$y1);
+ $y0 += $this->linespacing;
+ $x1 += $this->linespacing;
+ }
+ }
+}
+
+//=====================================================================
+// Class RectPatternLDiag
+// Implements left diagonal pattern
+//=====================================================================
+class RectPatternLDiag extends RectPattern {
+
+ function __construct($aColor="black",$aWeight=1,$aLineSpacing=12) {
+ $this->linespacing = $aLineSpacing;
+ parent::__construct($aColor,$aWeight);
+ }
+
+ function DoPattern($aImg) {
+ // --------------------
+ // |\ \ \ \ \ |
+ // | \ \ \ \ \|
+ // | \ \ \ \ |
+ // |------------------|
+ $xe = $this->rect->xe;
+ $ye = $this->rect->ye;
+ $x0 = $this->rect->x + round($this->linespacing/2);
+ $y0 = $this->rect->ye;
+ $x1 = $this->rect->x;
+ $y1 = $this->rect->ye - round($this->linespacing/2);
+
+ while($x0<=$xe && $y1>=$this->rect->y) {
+ $aImg->Line($x0,$y0,$x1,$y1);
+ $x0 += $this->linespacing;
+ $y1 -= $this->linespacing;
+ }
+ if( $xe-$x1 > $ye-$this->rect->y ) {
+ // Width larger than height
+ $x1 = $this->rect->x + ($this->rect->y-$y1);
+ $y0=$ye; $y1=$this->rect->y;
+ while( $x0 <= $xe ) {
+ $aImg->Line($x0,$y0,$x1,$y1);
+ $x0 += $this->linespacing;
+ $x1 += $this->linespacing;
+ }
+
+ $y0=$this->rect->ye - ($x0-$xe);
+ $x0=$xe;
+ }
+ else {
+ // Height larger than width
+ $diff = $x0-$xe;
+ $y0 = $ye-$diff;
+ $x0 = $xe;
+ while( $y1 >= $this->rect->y ) {
+ $aImg->Line($x0,$y0,$x1,$y1);
+ $y0 -= $this->linespacing;
+ $y1 -= $this->linespacing;
+ }
+ $diff = $this->rect->y - $y1;
+ $x1 = $this->rect->x + $diff;
+ $y1 = $this->rect->y;
+ }
+ while( $y0 >= $this->rect->y ) {
+ $aImg->Line($x0,$y0,$x1,$y1);
+ $y0 -= $this->linespacing;
+ $x1 += $this->linespacing;
+ }
+ }
+}
+
+//=====================================================================
+// Class RectPattern3DPlane
+// Implements "3D" plane pattern
+//=====================================================================
+class RectPattern3DPlane extends RectPattern {
+ private $alpha=50; // Parameter that specifies the distance
+ // to "simulated" horizon in pixel from the
+ // top of the band. Specifies how fast the lines
+ // converge.
+
+ function __construct($aColor="black",$aWeight=1) {
+ parent::__construct($aColor,$aWeight);
+ $this->SetDensity(10); // Slightly larger default
+ }
+
+ function SetHorizon($aHorizon) {
+ $this->alpha=$aHorizon;
+ }
+
+ function DoPattern($aImg) {
+ // "Fake" a nice 3D grid-effect.
+ $x0 = $this->rect->x + $this->rect->w/2;
+ $y0 = $this->rect->y;
+ $x1 = $x0;
+ $y1 = $this->rect->ye;
+ $x0_right = $x0;
+ $x1_right = $x1;
+
+ // BTW "apa" means monkey in Swedish but is really a shortform for
+ // "alpha+a" which was the labels I used on paper when I derived the
+ // geometric to get the 3D perspective right.
+ // $apa is the height of the bounding rectangle plus the distance to the
+ // artifical horizon (alpha)
+ $apa = $this->rect->h + $this->alpha;
+
+ // Three cases and three loops
+ // 1) The endpoint of the line ends on the bottom line
+ // 2) The endpoint ends on the side
+ // 3) Horizontal lines
+
+ // Endpoint falls on bottom line
+ $middle=$this->rect->x + $this->rect->w/2;
+ $dist=$this->linespacing;
+ $factor=$this->alpha /($apa);
+ while($x1>$this->rect->x) {
+ $aImg->Line($x0,$y0,$x1,$y1);
+ $aImg->Line($x0_right,$y0,$x1_right,$y1);
+ $x1 = $middle - $dist;
+ $x0 = $middle - $dist * $factor;
+ $x1_right = $middle + $dist;
+ $x0_right = $middle + $dist * $factor;
+ $dist += $this->linespacing;
+ }
+
+ // Endpoint falls on sides
+ $dist -= $this->linespacing;
+ $d=$this->rect->w/2;
+ $c = $apa - $d*$apa/$dist;
+ while( $x0>$this->rect->x ) {
+ $aImg->Line($x0,$y0,$this->rect->x,$this->rect->ye-$c);
+ $aImg->Line($x0_right,$y0,$this->rect->xe,$this->rect->ye-$c);
+ $dist += $this->linespacing;
+ $x0 = $middle - $dist * $factor;
+ $x1 = $middle - $dist;
+ $x0_right = $middle + $dist * $factor;
+ $c = $apa - $d*$apa/$dist;
+ }
+
+ // Horizontal lines
+ // They need some serious consideration since they are a function
+ // of perspective depth (alpha) and density (linespacing)
+ $x0=$this->rect->x;
+ $x1=$this->rect->xe;
+ $y=$this->rect->ye;
+
+ // The first line is drawn directly. Makes the loop below slightly
+ // more readable.
+ $aImg->Line($x0,$y,$x1,$y);
+ $hls = $this->linespacing;
+
+ // A correction factor for vertical "brick" line spacing to account for
+ // a) the difference in number of pixels hor vs vert
+ // b) visual apperance to make the first layer of "bricks" look more
+ // square.
+ $vls = $this->linespacing*0.6;
+
+ $ds = $hls*($apa-$vls)/$apa;
+ // Get the slope for the "perspective line" going from bottom right
+ // corner to top left corner of the "first" brick.
+
+ // Uncomment the following lines if you want to get a visual understanding
+ // of what this helpline does. BTW this mimics the way you would get the
+ // perspective right when drawing on paper.
+ /*
+ $x0 = $middle;
+ $y0 = $this->rect->ye;
+ $len=floor(($this->rect->ye-$this->rect->y)/$vls);
+ $x1 = $middle+round($len*$ds);
+ $y1 = $this->rect->ye-$len*$vls;
+ $aImg->PushColor("red");
+ $aImg->Line($x0,$y0,$x1,$y1);
+ $aImg->PopColor();
+ */
+
+ $y -= $vls;
+ $k=($this->rect->ye-($this->rect->ye-$vls))/($middle-($middle-$ds));
+ $dist = $hls;
+ while( $y>$this->rect->y ) {
+ $aImg->Line($this->rect->x,$y,$this->rect->xe,$y);
+ $adj = $k*$dist/(1+$dist*$k/$apa);
+ if( $adj < 2 ) $adj=1;
+ $y = $this->rect->ye - round($adj);
+ $dist += $hls;
+ }
+ }
+}
+
+//=====================================================================
+// Class RectPatternCross
+// Vert/Hor crosses
+//=====================================================================
+class RectPatternCross extends RectPattern {
+ private $vert=null;
+ private $hor=null;
+ function __construct($aColor="black",$aWeight=1) {
+ parent::__construct($aColor,$aWeight);
+ $this->vert = new RectPatternVert($aColor,$aWeight);
+ $this->hor = new RectPatternHor($aColor,$aWeight);
+ }
+
+ function SetOrder($aDepth) {
+ $this->vert->SetOrder($aDepth);
+ $this->hor->SetOrder($aDepth);
+ }
+
+ function SetPos($aRect) {
+ parent::SetPos($aRect);
+ $this->vert->SetPos($aRect);
+ $this->hor->SetPos($aRect);
+ }
+
+ function SetDensity($aDens) {
+ $this->vert->SetDensity($aDens);
+ $this->hor->SetDensity($aDens);
+ }
+
+ function DoPattern($aImg) {
+ $this->vert->DoPattern($aImg);
+ $this->hor->DoPattern($aImg);
+ }
+}
+
+//=====================================================================
+// Class RectPatternDiagCross
+// Vert/Hor crosses
+//=====================================================================
+
+class RectPatternDiagCross extends RectPattern {
+ private $left=null;
+ private $right=null;
+ function __construct($aColor="black",$aWeight=1) {
+ parent::__construct($aColor,$aWeight);
+ $this->right = new RectPatternRDiag($aColor,$aWeight);
+ $this->left = new RectPatternLDiag($aColor,$aWeight);
+ }
+
+ function SetOrder($aDepth) {
+ $this->left->SetOrder($aDepth);
+ $this->right->SetOrder($aDepth);
+ }
+
+ function SetPos($aRect) {
+ parent::SetPos($aRect);
+ $this->left->SetPos($aRect);
+ $this->right->SetPos($aRect);
+ }
+
+ function SetDensity($aDens) {
+ $this->left->SetDensity($aDens);
+ $this->right->SetDensity($aDens);
+ }
+
+ function DoPattern($aImg) {
+ $this->left->DoPattern($aImg);
+ $this->right->DoPattern($aImg);
+ }
+
+}
+
+//=====================================================================
+// Class RectPatternFactory
+// Factory class for rectangular pattern
+//=====================================================================
+class RectPatternFactory {
+ function __construct() {
+ // Empty
+ }
+ function Create($aPattern,$aColor,$aWeight=1) {
+ switch($aPattern) {
+ case BAND_RDIAG:
+ $obj = new RectPatternRDiag($aColor,$aWeight);
+ break;
+ case BAND_LDIAG:
+ $obj = new RectPatternLDiag($aColor,$aWeight);
+ break;
+ case BAND_SOLID:
+ $obj = new RectPatternSolid($aColor,$aWeight);
+ break;
+ case BAND_VLINE:
+ $obj = new RectPatternVert($aColor,$aWeight);
+ break;
+ case BAND_HLINE:
+ $obj = new RectPatternHor($aColor,$aWeight);
+ break;
+ case BAND_3DPLANE:
+ $obj = new RectPattern3DPlane($aColor,$aWeight);
+ break;
+ case BAND_HVCROSS:
+ $obj = new RectPatternCross($aColor,$aWeight);
+ break;
+ case BAND_DIAGCROSS:
+ $obj = new RectPatternDiagCross($aColor,$aWeight);
+ break;
+ default:
+ JpGraphError::RaiseL(16003,$aPattern);
+ //(" Unknown pattern specification ($aPattern)");
+ }
+ return $obj;
+ }
+}
+
+
+//=====================================================================
+// Class PlotBand
+// Factory class which is used by the client.
+// It is responsible for factoring the corresponding pattern
+// concrete class.
+//=====================================================================
+class PlotBand {
+ public $depth; // Determine if band should be over or under the plots
+ private $prect=null;
+ private $dir, $min, $max;
+
+ function __construct($aDir,$aPattern,$aMin,$aMax,$aColor="black",$aWeight=1,$aDepth=DEPTH_BACK) {
+ $f = new RectPatternFactory();
+ $this->prect = $f->Create($aPattern,$aColor,$aWeight);
+ if( is_numeric($aMin) && is_numeric($aMax) && ($aMin > $aMax) )
+ JpGraphError::RaiseL(16004);
+ //('Min value for plotband is larger than specified max value. Please correct.');
+ $this->dir = $aDir;
+ $this->min = $aMin;
+ $this->max = $aMax;
+ $this->depth=$aDepth;
+ }
+
+ // Set position. aRect contains absolute image coordinates
+ function SetPos($aRect) {
+ assert( $this->prect != null ) ;
+ $this->prect->SetPos($aRect);
+ }
+
+ function ShowFrame($aFlag=true) {
+ $this->prect->ShowFrame($aFlag);
+ }
+
+ // Set z-order. In front of pplot or in the back
+ function SetOrder($aDepth) {
+ $this->depth=$aDepth;
+ }
+
+ function SetDensity($aDens) {
+ $this->prect->SetDensity($aDens);
+ }
+
+ function GetDir() {
+ return $this->dir;
+ }
+
+ function GetMin() {
+ return $this->min;
+ }
+
+ function GetMax() {
+ return $this->max;
+ }
+
+ function PreStrokeAdjust($aGraph) {
+ // Nothing to do
+ }
+
+ // Display band
+ function Stroke($aImg,$aXScale,$aYScale) {
+ assert( $this->prect != null ) ;
+ if( $this->dir == HORIZONTAL ) {
+ if( $this->min === 'min' ) $this->min = $aYScale->GetMinVal();
+ if( $this->max === 'max' ) $this->max = $aYScale->GetMaxVal();
+
+ // Only draw the bar if it actually appears in the range
+ if ($this->min < $aYScale->GetMaxVal() && $this->max > $aYScale->GetMinVal()) {
+
+ // Trucate to limit of axis
+ $this->min = max($this->min, $aYScale->GetMinVal());
+ $this->max = min($this->max, $aYScale->GetMaxVal());
+
+ $x=$aXScale->scale_abs[0];
+ $y=$aYScale->Translate($this->max);
+ $width=$aXScale->scale_abs[1]-$aXScale->scale_abs[0]+1;
+ $height=abs($y-$aYScale->Translate($this->min))+1;
+ $this->prect->SetPos(new Rectangle($x,$y,$width,$height));
+ $this->prect->Stroke($aImg);
+ }
+ }
+ else { // VERTICAL
+ if( $this->min === 'min' ) $this->min = $aXScale->GetMinVal();
+ if( $this->max === 'max' ) $this->max = $aXScale->GetMaxVal();
+
+ // Only draw the bar if it actually appears in the range
+ if ($this->min < $aXScale->GetMaxVal() && $this->max > $aXScale->GetMinVal()) {
+
+ // Trucate to limit of axis
+ $this->min = max($this->min, $aXScale->GetMinVal());
+ $this->max = min($this->max, $aXScale->GetMaxVal());
+
+ $y=$aYScale->scale_abs[1];
+ $x=$aXScale->Translate($this->min);
+ $height=abs($aYScale->scale_abs[1]-$aYScale->scale_abs[0]);
+ $width=abs($x-$aXScale->Translate($this->max));
+ $this->prect->SetPos(new Rectangle($x,$y,$width,$height));
+ $this->prect->Stroke($aImg);
+ }
+ }
+ }
+}
+
+
+?>