source: trunk/xgraph/jpgraph/jpgraph_plotmark.inc @ 42

Last change on this file since 42 was 42, checked in by marrucho, 10 years ago
File size: 13.4 KB
Line 
1<?php
2//=======================================================================
3// File:        JPGRAPH_PLOTMARK.PHP
4// Description: Class file. Handles plotmarks
5// Created:     2003-03-21
6// Author:      Johan Persson (johanp@aditus.nu)
7// Ver:         $Id: jpgraph_plotmark.inc,v 1.9.2.5 2003/10/25 20:29:48 aditus Exp $
8//
9// License:     This code is released under QPL 1.0
10// Copyright (C) 2003 Johan Persson
11//========================================================================
12
13
14//========================================================================
15// CLASS ImgData
16// Description: Base class for all image data classes that contains the
17// real image data.
18//========================================================================
19class ImgData {
20    var $name = '';             // Each subclass gives a name
21    var $an = array();          // Data array names
22    var $colors = array();      // Available colors
23    var $index  = array();      // Index for colors
24    var $maxidx = 0 ;           // Max color index
25    var $anchor_x=0.5, $anchor_y=0.5 ;    // Where is the center of the image
26    // Create a GD image from the data and return a GD handle
27    function GetImg($aMark,$aIdx) {
28        $n = $this->an[$aMark];
29        if( is_string($aIdx) ) {
30            if( !in_array($aIdx,$this->colors) ) {
31                JpGraphError::Raise('This marker "'.($this->name).'" does not exist in color: '.$aIdx);
32                die();
33            }
34            $idx = $this->index[$aIdx];
35        }
36        elseif( !is_integer($aIdx) ||
37                (is_integer($aIdx) && $aIdx > $this->maxidx ) ) {
38            JpGraphError::Raise('Mark color index too large for marker "'.($this->name).'"');
39        }
40        else
41            $idx = $aIdx ;
42        return Image::CreateFromString(base64_decode($this->{$n}[$idx][1]));   
43    }
44    function GetAnchor() {
45        return array($this->anchor_x,$this->anchor_y);
46    }
47}
48
49
50// Keep a global flag cache to reduce memory usage
51$_gFlagCache=array(
52    1 => null,
53    2 => null,
54    3 => null,
55    4 => null,
56);
57// Only supposed to b called as statics
58class FlagCache {
59    function GetFlagImgByName($aSize,$aName) {
60        global $_gFlagCache;
61        require_once('jpgraph_flags.php');
62        if( $_gFlagCache[$aSize] === null ) {
63            $_gFlagCache[$aSize] =& new FlagImages($aSize);
64        }
65        $f =& $_gFlagCache[$aSize];
66        $idx = $f->GetIdxByName($aName,$aFullName);
67        return $f->GetImgByIdx($idx);
68    }
69}
70
71//===================================================
72// CLASS PlotMark
73// Description: Handles the plot marks in graphs
74//===================================================
75class PlotMark {
76    var $title, $show=true;
77    var $type,$weight=1;
78    var $color="black", $width=4, $fill_color="blue";
79    var $yvalue,$xvalue='',$csimtarget,$csimalt,$csimareas;
80    var $iFormatCallback="";
81    var $iFormatCallback2="";
82    var $markimg='',$iScale=1.0;
83    var $oldfilename='',$iFileName='';
84    var $imgdata_balls = null;
85    var $imgdata_diamonds = null;
86    var $imgdata_squares = null;
87    var $imgdata_bevels = null;
88    var $imgdata_stars = null;
89    var $imgdata_pushpins = null;
90
91//--------------
92// CONSTRUCTOR
93    function PlotMark() {
94        $this->title = new Text();
95        $this->title->Hide();
96        $this->csimareas = '';
97        $this->csimalt = '';
98        $this->type=-1;
99    }
100//---------------
101// PUBLIC METHODS       
102    function SetType($aType,$aFileName='',$aScale=1.0) {
103        $this->type = $aType;
104        if( $aType == MARK_IMG && $aFileName=='' ) {
105            JpGraphError::Raise('A filename must be specified if you set the mark type to MARK_IMG.');
106        }
107        $this->iFileName = $aFileName;
108        $this->iScale = $aScale;
109    }
110       
111    function SetCallback($aFunc) {
112        $this->iFormatCallback = $aFunc;
113    }
114
115    function SetCallbackYX($aFunc) {
116        $this->iFormatCallback2 = $aFunc;
117    }
118   
119    function GetType() {
120        return $this->type;
121    }
122       
123    function SetColor($aColor) {
124        $this->color=$aColor;
125    }
126       
127    function SetFillColor($aFillColor) {
128        $this->fill_color = $aFillColor;
129    }
130
131    function SetWeight($aWeight) {
132        $this->weight = $aWeight;
133    }
134
135    // Synonym for SetWidth()
136    function SetSize($aWidth) {
137        $this->width=$aWidth;
138    }
139       
140    function SetWidth($aWidth) {
141        $this->width=$aWidth;
142    }
143
144    function SetDefaultWidth() {
145        switch( $this->type ) {
146            case MARK_CIRCLE:
147            case MARK_FILLEDCIRCLE:
148                $this->width=4;
149                break;
150            default:
151                $this->width=7;
152        }
153    }
154       
155    function GetWidth() {
156        return $this->width;
157    }
158       
159    function Hide($aHide=true) {
160        $this->show = !$aHide;
161    }
162       
163    function Show($aShow=true) {
164        $this->show = $aShow;
165    }
166
167    function SetCSIMAltVal($aY,$aX='') {
168        $this->yvalue=$aY;
169        $this->xvalue=$aX;
170    }
171   
172    function SetCSIMTarget($aTarget) {
173        $this->csimtarget=$aTarget;
174    }
175   
176    function SetCSIMAlt($aAlt) {
177        $this->csimalt=$aAlt;
178    }
179   
180    function GetCSIMAreas(){
181        return $this->csimareas;
182    }
183       
184    function AddCSIMPoly($aPts) {
185        $coords = round($aPts[0]).", ".round($aPts[1]);
186        $n = count($aPts)/2;
187        for( $i=1; $i < $n; ++$i){
188            $coords .= ", ".round($aPts[2*$i]).", ".round($aPts[2*$i+1]);
189        }
190        $this->csimareas="";   
191        if( !empty($this->csimtarget) ) {
192            $this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->csimtarget."\"";
193            if( !empty($this->csimalt) ) {                                                                             
194                $tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue);
195                $this->csimareas .= " alt=\"$tmp\" title=\"$tmp\"";
196            }
197            $this->csimareas .= ">\n";
198        }
199    }
200   
201    function AddCSIMCircle($x,$y,$r) {
202        $x = round($x); $y=round($y); $r=round($r);
203        $this->csimareas="";   
204        if( !empty($this->csimtarget) ) {
205            $this->csimareas .= "<area shape=\"circle\" coords=\"$x,$y,$r\" href=\"".$this->csimtarget."\"";
206            if( !empty($this->csimalt) ) {                                                                             
207                $tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue);
208                $this->csimareas .= " alt=\"$tmp\" title=\"$tmp\"";
209            }
210            $this->csimareas .= ">\n";       
211        }
212    }
213       
214    function Stroke($img,$x,$y) {
215        if( !$this->show ) return;
216
217        if( $this->iFormatCallback != '' || $this->iFormatCallback2 != '' ) {
218
219            if( $this->iFormatCallback != '' ) {
220                $f = $this->iFormatCallback;
221                list($width,$color,$fcolor) = call_user_func($f,$this->yvalue);
222                $filename = $this->iFileName;
223                $imgscale = $this->iScale;
224            }
225            else {
226                $f = $this->iFormatCallback2;
227                list($width,$color,$fcolor,$filename,$imgscale) = call_user_func($f,$this->yvalue,$this->xvalue);
228                if( $filename=="" ) $filename = $this->iFileName;
229                if( $imgscale=="" ) $imgscale = $this->iScale;
230            }
231
232            if( $width=="" ) $width = $this->width;
233            if( $color=="" ) $color = $this->color;
234            if( $fcolor=="" ) $fcolor = $this->fill_color;
235
236        }
237        else {
238            $fcolor = $this->fill_color;
239            $color = $this->color;
240            $width = $this->width;
241            $filename = $this->iFileName;
242            $imgscale = $this->iScale;
243        }
244
245        if( $this->type == MARK_IMG ||
246            ($this->type >= MARK_FLAG1 && $this->type <= MARK_FLAG4 ) ||
247            $this->type >= MARK_IMG_PUSHPIN ) {
248
249            // Note: For the builtin images we use the "filename" parameter
250            // to denote the color
251            $anchor_x = 0.5;
252            $anchor_y = 0.5;
253            switch( $this->type ) {
254                case MARK_FLAG1:
255                case MARK_FLAG2:
256                case MARK_FLAG3:
257                case MARK_FLAG4:
258                    $this->markimg = FlagCache::GetFlagImgByName($this->type-MARK_FLAG1+1,$filename);
259                    break;
260
261                case MARK_IMG :
262                    // Load an image and use that as a marker
263                    // Small optimization, if we have already read an image don't
264                    // waste time reading it again.
265                    if( $this->markimg == '' || !($this->oldfilename === $filename) ) {
266                        $this->markimg = Graph::LoadBkgImage('',$filename);
267                        $this->oldfilename = $filename ;
268                    }
269                    break;
270
271                case MARK_IMG_PUSHPIN:
272                case MARK_IMG_SPUSHPIN:
273                case MARK_IMG_LPUSHPIN:
274                    if( $this->imgdata_pushpins == null ) {
275                        require_once 'imgdata_pushpins.inc';
276                        $this->imgdata_pushpins = new ImgData_PushPins();
277                    }
278                    $this->markimg = $this->imgdata_pushpins->GetImg($this->type,$filename);
279                    list($anchor_x,$anchor_y) = $this->imgdata_pushpins->GetAnchor();
280                    break;
281
282                case MARK_IMG_SQUARE:
283                    if( $this->imgdata_squares == null ) {
284                        require_once 'imgdata_squares.inc';
285                        $this->imgdata_squares = new ImgData_Squares();
286                    }
287                    $this->markimg = $this->imgdata_squares->GetImg($this->type,$filename);
288                    list($anchor_x,$anchor_y) = $this->imgdata_squares->GetAnchor();
289                    break;
290
291                case MARK_IMG_STAR:
292                    if( $this->imgdata_stars == null ) {
293                        require_once 'imgdata_stars.inc';
294                        $this->imgdata_stars = new ImgData_Stars();
295                    }
296                    $this->markimg = $this->imgdata_stars->GetImg($this->type,$filename);
297                    list($anchor_x,$anchor_y) = $this->imgdata_stars->GetAnchor();
298                    break;
299
300                case MARK_IMG_BEVEL:
301                    if( $this->imgdata_bevels == null ) {
302                        require_once 'imgdata_bevels.inc';
303                        $this->imgdata_bevels = new ImgData_Bevels();
304                    }
305                    $this->markimg = $this->imgdata_bevels->GetImg($this->type,$filename);
306                    list($anchor_x,$anchor_y) = $this->imgdata_bevels->GetAnchor();
307                    break;
308
309                case MARK_IMG_DIAMOND:
310                    if( $this->imgdata_diamonds == null ) {
311                        require_once 'imgdata_diamonds.inc';
312                        $this->imgdata_diamonds = new ImgData_Diamonds();
313                    }
314                    $this->markimg = $this->imgdata_diamonds->GetImg($this->type,$filename);
315                    list($anchor_x,$anchor_y) = $this->imgdata_diamonds->GetAnchor();
316                    break;
317
318                case MARK_IMG_BALL:                 
319                case MARK_IMG_SBALL:               
320                case MARK_IMG_MBALL:               
321                case MARK_IMG_LBALL:               
322                    if( $this->imgdata_balls == null ) {
323                        require_once 'imgdata_balls.inc';
324                        $this->imgdata_balls = new ImgData_Balls();
325                    }
326                    $this->markimg = $this->imgdata_balls->GetImg($this->type,$filename);
327                    list($anchor_x,$anchor_y) = $this->imgdata_balls->GetAnchor();
328                    break;
329            }
330
331            $w = $img->GetWidth($this->markimg);
332            $h = $img->GetHeight($this->markimg);
333           
334            $dw = round($imgscale * $w );
335            $dh = round($imgscale * $h );
336
337            $dx = round($x-$dw*$anchor_x);
338            $dy = round($y-$dh*$anchor_y);
339           
340            $this->width = max($dx,$dy);
341           
342            $img->Copy($this->markimg,$dx,$dy,0,0,$dw,$dh,$w,$h);
343            if( !empty($this->csimtarget) ) {
344                $this->csimareas = "<area shape=\"rect\" coords=\"".
345                    $dx.','.$dy.','.round($dx+$dw).','.round($dy+$dh).'" '.
346                    "href=\"".$this->csimtarget."\"";
347                if( !empty($this->csimalt) ) {
348                    $tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue);
349                    $this->csimareas .= " alt=\"$tmp\" title=\"$tmp\"";
350                }
351                $this->csimareas .= ">\n";
352            }
353           
354            // Stroke title
355            $this->title->Align("center","top");
356            $this->title->Stroke($img,$x,$y+round($dh/2));                     
357            return;
358        }
359
360        $weight = $this->weight;
361        $dx=round($width/2,0);
362        $dy=round($width/2,0);
363        $pts=0;         
364
365        switch( $this->type ) {
366            case MARK_SQUARE:
367                $c[]=$x-$dx;$c[]=$y-$dy;
368                $c[]=$x+$dx;$c[]=$y-$dy;
369                $c[]=$x+$dx;$c[]=$y+$dy;
370                $c[]=$x-$dx;$c[]=$y+$dy;
371                $c[]=$x-$dx;$c[]=$y-$dy;
372                $pts=5;
373                break;
374            case MARK_UTRIANGLE:
375                ++$dx;++$dy;
376                $c[]=$x-$dx;$c[]=$y+0.87*$dy;   // tan(60)/2*$dx
377                $c[]=$x;$c[]=$y-0.87*$dy;
378                $c[]=$x+$dx;$c[]=$y+0.87*$dy;
379                $c[]=$x-$dx;$c[]=$y+0.87*$dy;   // tan(60)/2*$dx
380                $pts=4;
381                break;
382            case MARK_DTRIANGLE:
383                ++$dx;++$dy;                   
384                $c[]=$x;$c[]=$y+0.87*$dy;       // tan(60)/2*$dx
385                $c[]=$x-$dx;$c[]=$y-0.87*$dy;
386                $c[]=$x+$dx;$c[]=$y-0.87*$dy;
387                $c[]=$x;$c[]=$y+0.87*$dy;       // tan(60)/2*$dx
388                $pts=4;
389                break;                         
390            case MARK_DIAMOND:
391                $c[]=$x;$c[]=$y+$dy;
392                $c[]=$x-$dx;$c[]=$y;
393                $c[]=$x;$c[]=$y-$dy;
394                $c[]=$x+$dx;$c[]=$y;
395                $c[]=$x;$c[]=$y+$dy;
396                $pts=5;
397                break; 
398            case MARK_LEFTTRIANGLE:
399                $c[]=$x;$c[]=$y;
400                $c[]=$x;$c[]=$y+2*$dy;
401                $c[]=$x+$dx*2;$c[]=$y;
402                $c[]=$x;$c[]=$y;
403                $pts=4;
404                break;
405            case MARK_RIGHTTRIANGLE:
406                $c[]=$x-$dx*2;$c[]=$y;
407                $c[]=$x;$c[]=$y+2*$dy;
408                $c[]=$x;$c[]=$y;
409                $c[]=$x-$dx*2;$c[]=$y;
410                $pts=4;
411                break;
412            case MARK_FLASH:
413                $dy *= 2;
414                $c[]=$x+$dx/2; $c[]=$y-$dy;
415                $c[]=$x-$dx+$dx/2; $c[]=$y+$dy*0.7-$dy;
416                $c[]=$x+$dx/2; $c[]=$y+$dy*1.3-$dy;
417                $c[]=$x-$dx+$dx/2; $c[]=$y+2*$dy-$dy;
418                $img->SetLineWeight($weight);
419                $img->SetColor($color);                                 
420                $img->Polygon($c);
421                $img->SetLineWeight(1);
422                $this->AddCSIMPoly($c);
423                break;
424        }
425
426        if( $pts>0 ) {
427            $this->AddCSIMPoly($c);
428            $img->SetLineWeight($weight);
429            $img->SetColor($fcolor);                                                           
430            $img->FilledPolygon($c);
431            $img->SetColor($color);                                     
432            $img->Polygon($c);
433            $img->SetLineWeight(1);
434        }
435        elseif( $this->type==MARK_CIRCLE ) {
436            $img->SetColor($color);                                     
437            $img->Circle($x,$y,$width);
438            $this->AddCSIMCircle($x,$y,$width);
439        }
440        elseif( $this->type==MARK_FILLEDCIRCLE ) {
441            $img->SetColor($fcolor);           
442            $img->FilledCircle($x,$y,$width);
443            $img->SetColor($color);     
444            $img->Circle($x,$y,$width);
445            $this->AddCSIMCircle($x,$y,$width);
446        }
447        elseif( $this->type==MARK_CROSS ) {
448            // Oversize by a pixel to match the X
449            $img->SetColor($color);
450            $img->SetLineWeight($weight);
451            $img->Line($x,$y+$dy+1,$x,$y-$dy-1);
452            $img->Line($x-$dx-1,$y,$x+$dx+1,$y);
453            $this->AddCSIMCircle($x,$y,$dx);       
454        }
455        elseif( $this->type==MARK_X ) {
456            $img->SetColor($color);
457            $img->SetLineWeight($weight);
458            $img->Line($x+$dx,$y+$dy,$x-$dx,$y-$dy);
459            $img->Line($x-$dx,$y+$dy,$x+$dx,$y-$dy);           
460            $this->AddCSIMCircle($x,$y,$dx+$dy);                   
461        }                       
462        elseif( $this->type==MARK_STAR ) {
463            $img->SetColor($color);
464            $img->SetLineWeight($weight);
465            $img->Line($x+$dx,$y+$dy,$x-$dx,$y-$dy);
466            $img->Line($x-$dx,$y+$dy,$x+$dx,$y-$dy);
467            // Oversize by a pixel to match the X                               
468            $img->Line($x,$y+$dy+1,$x,$y-$dy-1);
469            $img->Line($x-$dx-1,$y,$x+$dx+1,$y);
470            $this->AddCSIMCircle($x,$y,$dx+$dy);           
471        }
472               
473        // Stroke title
474        $this->title->Align("center","center");
475        $this->title->Stroke($img,$x,$y);                       
476    }
477} // Class
478
479
480?>
Note: See TracBrowser for help on using the repository browser.