Subversion Repositories Sites.tela-botanica.org

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4 david 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.1 2004/06/15 10:13:19 jpm 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
//========================================================================
19
class 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 imagecreatefromstring(base64_decode($this->{$n}[$idx][1]));
43
    }
44
    function GetAnchor() {
45
	return array($this->anchor_x,$this->anchor_y);
46
    }
47
}
48
 
49
 
50
//===================================================
51
// CLASS PlotMark
52
// Description: Handles the plot marks in graphs
53
//===================================================
54
class PlotMark {
55
    var $title, $show=true;
56
    var $type,$weight=1;
57
    var $color="black", $width=4, $fill_color="blue";
58
    var $yvalue,$xvalue='',$csimtarget,$csimalt,$csimareas;
59
    var $iFormatCallback="";
60
    var $iFormatCallback2="";
61
    var $markimg='',$iScale=1.0;
62
    var $oldfilename='',$iFileName='';
63
    var $imgdata_balls = null;
64
    var $imgdata_diamonds = null;
65
    var $imgdata_squares = null;
66
    var $imgdata_bevels = null;
67
    var $imgdata_stars = null;
68
    var $imgdata_pushpins = null;
69
 
70
//--------------
71
// CONSTRUCTOR
72
    function PlotMark() {
73
	$this->title = new Text();
74
	$this->title->Hide();
75
	$this->csimareas = '';
76
	$this->csimalt = '';
77
	$this->type=-1;
78
    }
79
//---------------
80
// PUBLIC METHODS
81
    function SetType($aType,$aFileName='',$aScale=1.0) {
82
	$this->type = $aType;
83
	if( $aType == MARK_IMG && $aFileName=='' ) {
84
	    JpGraphError::Raise('A filename must be specified if you set the mark type to MARK_IMG.');
85
	}
86
	$this->iFileName = $aFileName;
87
	$this->iScale = $aScale;
88
    }
89
 
90
    function SetCallback($aFunc) {
91
	$this->iFormatCallback = $aFunc;
92
    }
93
 
94
    function SetCallbackYX($aFunc) {
95
	$this->iFormatCallback2 = $aFunc;
96
    }
97
 
98
    function GetType() {
99
	return $this->type;
100
    }
101
 
102
    function SetColor($aColor) {
103
	$this->color=$aColor;
104
    }
105
 
106
    function SetFillColor($aFillColor) {
107
	$this->fill_color = $aFillColor;
108
    }
109
 
110
    function SetWeight($aWeight) {
111
	$this->weight = $aWeight;
112
    }
113
 
114
    // Synonym for SetWidth()
115
    function SetSize($aWidth) {
116
	$this->width=$aWidth;
117
    }
118
 
119
    function SetWidth($aWidth) {
120
	$this->width=$aWidth;
121
    }
122
 
123
    function SetDefaultWidth() {
124
	switch( $this->type ) {
125
	    case MARK_CIRCLE:
126
	    case MARK_FILLEDCIRCLE:
127
		$this->width=4;
128
		break;
129
	    default:
130
		$this->width=7;
131
	}
132
    }
133
 
134
    function GetWidth() {
135
	return $this->width;
136
    }
137
 
138
    function Hide($aHide=true) {
139
	$this->show = !$aHide;
140
    }
141
 
142
    function Show($aShow=true) {
143
	$this->show = $aShow;
144
    }
145
 
146
    function SetCSIMAltVal($aY,$aX='') {
147
        $this->yvalue=$aY;
148
        $this->xvalue=$aX;
149
    }
150
 
151
    function SetCSIMTarget($aTarget) {
152
        $this->csimtarget=$aTarget;
153
    }
154
 
155
    function SetCSIMAlt($aAlt) {
156
        $this->csimalt=$aAlt;
157
    }
158
 
159
    function GetCSIMAreas(){
160
        return $this->csimareas;
161
    }
162
 
163
    function AddCSIMPoly($aPts) {
164
        $coords = round($aPts[0]).", ".round($aPts[1]);
165
        $n = count($aPts)/2;
166
        for( $i=1; $i < $n; ++$i){
167
            $coords .= ", ".round($aPts[2*$i]).", ".round($aPts[2*$i+1]);
168
        }
169
        $this->csimareas="";
170
        if( !empty($this->csimtarget) ) {
171
	    $this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->csimtarget."\"";
172
	    if( !empty($this->csimalt) ) {
173
		$tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue);
174
		$this->csimareas .= " alt=\"$tmp\" title=\"$tmp\"";
175
	    }
176
	    $this->csimareas .= ">\n";
177
	}
178
    }
179
 
180
    function AddCSIMCircle($x,$y,$r) {
181
    	$x = round($x); $y=round($y); $r=round($r);
182
        $this->csimareas="";
183
        if( !empty($this->csimtarget) ) {
184
	    $this->csimareas .= "<area shape=\"circle\" coords=\"$x,$y,$r\" href=\"".$this->csimtarget."\"";
185
    	    if( !empty($this->csimalt) ) {
186
		$tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue);
187
		$this->csimareas .= " alt=\"$tmp\" title=\"$tmp\"";
188
	    }
189
            $this->csimareas .= ">\n";
190
        }
191
    }
192
 
193
    function Stroke($img,$x,$y) {
194
	if( !$this->show ) return;
195
 
196
	if( $this->iFormatCallback != '' || $this->iFormatCallback2 != '' ) {
197
 
198
	    if( $this->iFormatCallback != '' ) {
199
		$f = $this->iFormatCallback;
200
		list($width,$color,$fcolor) = $f($this->yvalue);
201
		$filename = $this->iFileName;
202
		$imgscale = $this->iScale;
203
	    }
204
	    else {
205
		$f = $this->iFormatCallback2;
206
		list($width,$color,$fcolor,$filename,$imgscale) = $f($this->yvalue,$this->xvalue);
207
		if( $filename=="" ) $filename = $this->iFileName;
208
		if( $imgscale=="" ) $imgscale = $this->iScale;
209
	    }
210
 
211
	    if( $width=="" ) $width = $this->width;
212
	    if( $color=="" ) $color = $this->color;
213
	    if( $fcolor=="" ) $fcolor = $this->fill_color;
214
 
215
	}
216
	else {
217
	    $fcolor = $this->fill_color;
218
	    $color = $this->color;
219
	    $width = $this->width;
220
	    $filename = $this->iFileName;
221
	    $imgscale = $this->iScale;
222
	}
223
 
224
 
225
	if( $this->type == MARK_IMG || $this->type >= MARK_IMG_PUSHPIN ) {
226
 
227
	    // Note: For the builtin images we use the "filename" parameter
228
	    // to denote the color
229
	    $anchor_x = 0.5;
230
	    $anchor_y = 0.5;
231
	    switch( $this->type ) {
232
		case MARK_IMG :
233
		    // Load an image and use that as a marker
234
		    // Small optimization, if we have already read an image don't
235
		    // waste time reading it again.
236
		    if( $this->markimg == '' || !($this->oldfilename === $filename) ) {
237
			$this->markimg = Graph::LoadBkgImage('',$filename);
238
			$this->oldfilename = $filename ;
239
		    }
240
		    break;
241
 
242
		case MARK_IMG_PUSHPIN:
243
		case MARK_IMG_SPUSHPIN:
244
		case MARK_IMG_LPUSHPIN:
245
		    if( $this->imgdata_pushpins == null ) {
246
			require_once 'imgdata_pushpins.inc';
247
			$this->imgdata_pushpins = new ImgData_PushPins();
248
		    }
249
		    $this->markimg = $this->imgdata_pushpins->GetImg($this->type,$filename);
250
		    list($anchor_x,$anchor_y) = $this->imgdata_pushpins->GetAnchor();
251
		    break;
252
 
253
		case MARK_IMG_SQUARE:
254
		    if( $this->imgdata_squares == null ) {
255
			require_once 'imgdata_squares.inc';
256
			$this->imgdata_squares = new ImgData_Squares();
257
		    }
258
		    $this->markimg = $this->imgdata_squares->GetImg($this->type,$filename);
259
		    list($anchor_x,$anchor_y) = $this->imgdata_squares->GetAnchor();
260
		    break;
261
 
262
		case MARK_IMG_STAR:
263
		    if( $this->imgdata_stars == null ) {
264
			require_once 'imgdata_stars.inc';
265
			$this->imgdata_stars = new ImgData_Stars();
266
		    }
267
		    $this->markimg = $this->imgdata_stars->GetImg($this->type,$filename);
268
		    list($anchor_x,$anchor_y) = $this->imgdata_stars->GetAnchor();
269
		    break;
270
 
271
		case MARK_IMG_BEVEL:
272
		    if( $this->imgdata_bevels == null ) {
273
			require_once 'imgdata_bevels.inc';
274
			$this->imgdata_bevels = new ImgData_Bevels();
275
		    }
276
		    $this->markimg = $this->imgdata_bevels->GetImg($this->type,$filename);
277
		    list($anchor_x,$anchor_y) = $this->imgdata_bevels->GetAnchor();
278
		    break;
279
 
280
		case MARK_IMG_DIAMOND:
281
		    if( $this->imgdata_diamonds == null ) {
282
			require_once 'imgdata_diamonds.inc';
283
			$this->imgdata_diamonds = new ImgData_Diamonds();
284
		    }
285
		    $this->markimg = $this->imgdata_diamonds->GetImg($this->type,$filename);
286
		    list($anchor_x,$anchor_y) = $this->imgdata_diamonds->GetAnchor();
287
		    break;
288
 
289
		case MARK_IMG_BALL:
290
		case MARK_IMG_SBALL:
291
		case MARK_IMG_MBALL:
292
		case MARK_IMG_LBALL:
293
		    if( $this->imgdata_balls == null ) {
294
			require_once 'imgdata_balls.inc';
295
			$this->imgdata_balls = new ImgData_Balls();
296
		    }
297
		    $this->markimg = $this->imgdata_balls->GetImg($this->type,$filename);
298
		    list($anchor_x,$anchor_y) = $this->imgdata_balls->GetAnchor();
299
		    break;
300
	    }
301
 
302
	    $w = imagesx($this->markimg);
303
	    $h = imagesy($this->markimg);
304
 
305
	    $dw = round($imgscale * $w );
306
	    $dh = round($imgscale * $h );
307
 
308
	    $dx = round($x-$dw*$anchor_x);
309
	    $dy = round($y-$dh*$anchor_y);
310
 
311
	    $this->width = max($dx,$dy);
312
 
313
	    $cp = $GLOBALS['copyfunc'] ;
314
	    $cp($img->img,$this->markimg,$dx,$dy,0,0,$dw,$dh,$w,$h);
315
	    if( !empty($this->csimtarget) ) {
316
		$this->csimareas = "<area shape=\"rect\" coords=\"".
317
		    $dx.','.$dy.','.round($dx+$dw).','.round($dy+$dh).'" '.
318
		    "href=\"".$this->csimtarget."\"";
319
		if( !empty($this->csimalt) ) {
320
		    $tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue);
321
		    $this->csimareas .= " alt=\"$tmp\" title=\"$tmp\"";
322
		}
323
		$this->csimareas .= ">\n";
324
	    }
325
 
326
	    // Stroke title
327
	    $this->title->Align("center","top");
328
	    $this->title->Stroke($img,$x,$y+round($dh/2));
329
	    return;
330
	}
331
 
332
	$weight = $this->weight;
333
	$dx=round($width/2,0);
334
	$dy=round($width/2,0);
335
	$pts=0;
336
 
337
	switch( $this->type ) {
338
	    case MARK_SQUARE:
339
		$c[]=$x-$dx;$c[]=$y-$dy;
340
		$c[]=$x+$dx;$c[]=$y-$dy;
341
		$c[]=$x+$dx;$c[]=$y+$dy;
342
		$c[]=$x-$dx;$c[]=$y+$dy;
343
		$c[]=$x-$dx;$c[]=$y-$dy;
344
		$pts=5;
345
		break;
346
	    case MARK_UTRIANGLE:
347
		++$dx;++$dy;
348
		$c[]=$x-$dx;$c[]=$y+0.87*$dy;	// tan(60)/2*$dx
349
		$c[]=$x;$c[]=$y-0.87*$dy;
350
		$c[]=$x+$dx;$c[]=$y+0.87*$dy;
351
		$c[]=$x-$dx;$c[]=$y+0.87*$dy;	// tan(60)/2*$dx
352
		$pts=4;
353
		break;
354
	    case MARK_DTRIANGLE:
355
		++$dx;++$dy;
356
		$c[]=$x;$c[]=$y+0.87*$dy;	// tan(60)/2*$dx
357
		$c[]=$x-$dx;$c[]=$y-0.87*$dy;
358
		$c[]=$x+$dx;$c[]=$y-0.87*$dy;
359
		$c[]=$x;$c[]=$y+0.87*$dy;	// tan(60)/2*$dx
360
		$pts=4;
361
		break;
362
	    case MARK_DIAMOND:
363
		$c[]=$x;$c[]=$y+$dy;
364
		$c[]=$x-$dx;$c[]=$y;
365
		$c[]=$x;$c[]=$y-$dy;
366
		$c[]=$x+$dx;$c[]=$y;
367
		$c[]=$x;$c[]=$y+$dy;
368
		$pts=5;
369
		break;
370
	    case MARK_LEFTTRIANGLE:
371
		$c[]=$x;$c[]=$y;
372
		$c[]=$x;$c[]=$y+2*$dy;
373
		$c[]=$x+$dx*2;$c[]=$y;
374
		$c[]=$x;$c[]=$y;
375
		$pts=4;
376
		break;
377
	    case MARK_RIGHTTRIANGLE:
378
		$c[]=$x-$dx*2;$c[]=$y;
379
		$c[]=$x;$c[]=$y+2*$dy;
380
		$c[]=$x;$c[]=$y;
381
		$c[]=$x-$dx*2;$c[]=$y;
382
		$pts=4;
383
		break;
384
	    case MARK_FLASH:
385
		$dy *= 2;
386
		$c[]=$x+$dx/2; $c[]=$y-$dy;
387
		$c[]=$x-$dx+$dx/2; $c[]=$y+$dy*0.7-$dy;
388
		$c[]=$x+$dx/2; $c[]=$y+$dy*1.3-$dy;
389
		$c[]=$x-$dx+$dx/2; $c[]=$y+2*$dy-$dy;
390
		$img->SetLineWeight($weight);
391
		$img->SetColor($color);
392
		$img->Polygon($c);
393
		$img->SetLineWeight(1);
394
		$this->AddCSIMPoly($c);
395
		break;
396
	}
397
 
398
	if( $pts>0 ) {
399
	    $this->AddCSIMPoly($c);
400
	    $img->SetLineWeight($weight);
401
	    $img->SetColor($fcolor);
402
	    $img->FilledPolygon($c);
403
	    $img->SetColor($color);
404
	    $img->Polygon($c);
405
	    $img->SetLineWeight(1);
406
	}
407
	elseif( $this->type==MARK_CIRCLE ) {
408
	    $img->SetColor($color);
409
	    $img->Circle($x,$y,$width);
410
	    $this->AddCSIMCircle($x,$y,$width);
411
	}
412
	elseif( $this->type==MARK_FILLEDCIRCLE ) {
413
	    $img->SetColor($fcolor);
414
	    $img->FilledCircle($x,$y,$width);
415
	    $img->SetColor($color);
416
	    $img->Circle($x,$y,$width+1);
417
	    $this->AddCSIMCircle($x,$y,$width);
418
	}
419
	elseif( $this->type==MARK_CROSS ) {
420
	    // Oversize by a pixel to match the X
421
	    $img->SetColor($color);
422
	    $img->SetLineWeight($weight);
423
	    $img->Line($x,$y+$dy+1,$x,$y-$dy-1);
424
	    $img->Line($x-$dx-1,$y,$x+$dx+1,$y);
425
	    $this->AddCSIMCircle($x,$y,$dx);
426
	}
427
	elseif( $this->type==MARK_X ) {
428
	    $img->SetColor($color);
429
	    $img->SetLineWeight($weight);
430
	    $img->Line($x+$dx,$y+$dy,$x-$dx,$y-$dy);
431
	    $img->Line($x-$dx,$y+$dy,$x+$dx,$y-$dy);
432
	    $this->AddCSIMCircle($x,$y,$dx+$dy);
433
	}
434
	elseif( $this->type==MARK_STAR ) {
435
	    $img->SetColor($color);
436
	    $img->SetLineWeight($weight);
437
	    $img->Line($x+$dx,$y+$dy,$x-$dx,$y-$dy);
438
	    $img->Line($x-$dx,$y+$dy,$x+$dx,$y-$dy);
439
	    // Oversize by a pixel to match the X
440
	    $img->Line($x,$y+$dy+1,$x,$y-$dy-1);
441
	    $img->Line($x-$dx-1,$y,$x+$dx+1,$y);
442
	    $this->AddCSIMCircle($x,$y,$dx+$dy);
443
	}
444
 
445
	// Stroke title
446
	$this->title->Align("center","center");
447
	$this->title->Stroke($img,$x,$y);
448
    }
449
} // Class
450
 
451
 
452
?>