Subversion Repositories Sites.obs-saisons.fr

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 aurelien 1
<?php
2
//=======================================================================
3
// File:	JPGRAPH_PLOTBAND.PHP
4
// Description:	PHP4 Graph Plotting library. Extension module.
5
// Created: 	2004-02-18
6
// Ver:		$Id: jpgraph_plotband.php 782 2006-10-08 08:09:02Z ljp $
7
//
8
// Copyright (c) Aditus Consulting. All rights reserved.
9
//========================================================================
10
 
11
// Constants for types of static bands in plot area
12
DEFINE("BAND_RDIAG",1);	// Right diagonal lines
13
DEFINE("BAND_LDIAG",2); // Left diagonal lines
14
DEFINE("BAND_SOLID",3); // Solid one color
15
DEFINE("BAND_VLINE",4); // Vertical lines
16
DEFINE("BAND_HLINE",5);  // Horizontal lines
17
DEFINE("BAND_3DPLANE",6);  // "3D" Plane
18
DEFINE("BAND_HVCROSS",7);  // Vertical/Hor crosses
19
DEFINE("BAND_DIAGCROSS",8); // Diagonal crosses
20
 
21
 
22
// Utility class to hold coordinates for a rectangle
23
class Rectangle {
24
    var $x,$y,$w,$h;
25
    var $xe, $ye;
26
    function Rectangle($aX,$aY,$aWidth,$aHeight) {
27
	$this->x=$aX;
28
	$this->y=$aY;
29
	$this->w=$aWidth;
30
	$this->h=$aHeight;
31
	$this->xe=$aX+$aWidth-1;
32
	$this->ye=$aY+$aHeight-1;
33
    }
34
}
35
 
36
//=====================================================================
37
// Class RectPattern
38
// Base class for pattern hierarchi that is used to display patterned
39
// bands on the graph. Any subclass that doesn't override Stroke()
40
// must at least implement method DoPattern(&$aImg) which is responsible
41
// for drawing the pattern onto the graph.
42
//=====================================================================
43
class RectPattern {
44
    var $color;
45
    var $weight;
46
    var $rect=null;
47
    var $doframe=true;
48
    var $linespacing;	// Line spacing in pixels
49
    var $iBackgroundColor=-1;  // Default is no background fill
50
 
51
    function RectPattern($aColor,$aWeight=1) {
52
	$this->color = $aColor;
53
	$this->weight = $aWeight;
54
    }
55
 
56
    function SetBackground($aBackgroundColor) {
57
	$this->iBackgroundColor=$aBackgroundColor;
58
    }
59
 
60
    function SetPos(&$aRect) {
61
	$this->rect = $aRect;
62
    }
63
 
64
    function ShowFrame($aShow=true) {
65
	$this->doframe=$aShow;
66
    }
67
 
68
    function SetDensity($aDens) {
69
	if( $aDens < 1 || $aDens > 100 )
70
	    JpGraphError::RaiseL(16001,$aDens);
71
//(" Desity for pattern must be between 1 and 100. (You tried $aDens)");
72
	// 1% corresponds to linespacing=50
73
	// 100 % corresponds to linespacing 1
74
	$this->linespacing = floor(((100-$aDens)/100.0)*50)+1;
75
 
76
    }
77
 
78
    function Stroke(&$aImg) {
79
	if( $this->rect == null )
80
	    JpGraphError::RaiseL(16002);
81
//(" No positions specified for pattern.");
82
 
83
	if( !(is_numeric($this->iBackgroundColor) && $this->iBackgroundColor==-1) ) {
84
	    $aImg->SetColor($this->iBackgroundColor);
85
	    $aImg->FilledRectangle($this->rect->x,$this->rect->y,$this->rect->xe,$this->rect->ye);
86
	}
87
 
88
	$aImg->SetColor($this->color);
89
	$aImg->SetLineWeight($this->weight);
90
 
91
	// Virtual function implemented by subclass
92
	$this->DoPattern($aImg);
93
 
94
	// Frame around the pattern area
95
	if( $this->doframe )
96
	    $aImg->Rectangle($this->rect->x,$this->rect->y,$this->rect->xe,$this->rect->ye);
97
    }
98
 
99
}
100
 
101
 
102
//=====================================================================
103
// Class RectPatternSolid
104
// Implements a solid band
105
//=====================================================================
106
class RectPatternSolid extends RectPattern {
107
 
108
    function RectPatternSolid($aColor="black",$aWeight=1) {
109
	parent::RectPattern($aColor,$aWeight);
110
    }
111
 
112
    function DoPattern(&$aImg) {
113
	$aImg->SetColor($this->color);
114
	$aImg->FilledRectangle($this->rect->x,$this->rect->y,
115
			       $this->rect->xe,$this->rect->ye);
116
    }
117
}
118
 
119
//=====================================================================
120
// Class RectPatternHor
121
// Implements horizontal line pattern
122
//=====================================================================
123
class RectPatternHor extends RectPattern {
124
 
125
    function RectPatternHor($aColor="black",$aWeight=1,$aLineSpacing=7) {
126
	parent::RectPattern($aColor,$aWeight);
127
	$this->linespacing = $aLineSpacing;
128
    }
129
 
130
    function DoPattern(&$aImg) {
131
	$x0 = $this->rect->x;
132
	$x1 = $this->rect->xe;
133
	$y = $this->rect->y;
134
	while( $y < $this->rect->ye ) {
135
	    $aImg->Line($x0,$y,$x1,$y);
136
	    $y += $this->linespacing;
137
	}
138
    }
139
}
140
 
141
//=====================================================================
142
// Class RectPatternVert
143
// Implements vertical line pattern
144
//=====================================================================
145
class RectPatternVert extends RectPattern {
146
    var $linespacing=10;	// Line spacing in pixels
147
 
148
    function RectPatternVert($aColor="black",$aWeight=1,$aLineSpacing=7) {
149
	parent::RectPattern($aColor,$aWeight);
150
	$this->linespacing = $aLineSpacing;
151
    }
152
 
153
    //--------------------
154
    // Private methods
155
    //
156
    function DoPattern(&$aImg) {
157
	$x = $this->rect->x;
158
	$y0 = $this->rect->y;
159
	$y1 = $this->rect->ye;
160
	while( $x < $this->rect->xe ) {
161
	    $aImg->Line($x,$y0,$x,$y1);
162
	    $x += $this->linespacing;
163
	}
164
    }
165
}
166
 
167
 
168
//=====================================================================
169
// Class RectPatternRDiag
170
// Implements right diagonal pattern
171
//=====================================================================
172
class RectPatternRDiag extends RectPattern {
173
    var $linespacing;	// Line spacing in pixels
174
 
175
    function RectPatternRDiag($aColor="black",$aWeight=1,$aLineSpacing=12) {
176
	parent::RectPattern($aColor,$aWeight);
177
	$this->linespacing = $aLineSpacing;
178
    }
179
 
180
    function DoPattern(&$aImg) {
181
	//  --------------------
182
	//  | /   /   /   /   /|
183
	//  |/   /   /   /   / |
184
	//  |   /   /   /   /  |
185
	//  --------------------
186
	$xe = $this->rect->xe;
187
	$ye = $this->rect->ye;
188
	$x0 = $this->rect->x + round($this->linespacing/2);
189
	$y0 = $this->rect->y;
190
	$x1 = $this->rect->x;
191
	$y1 = $this->rect->y + round($this->linespacing/2);
192
 
193
	while($x0<=$xe && $y1<=$ye) {
194
	    $aImg->Line($x0,$y0,$x1,$y1);
195
	    $x0 += $this->linespacing;
196
	    $y1 += $this->linespacing;
197
	}
198
 
199
	if( $xe-$x1 > $ye-$y0 ) {
200
	    // Width larger than height
201
	    $x1 = $this->rect->x + ($y1-$ye);
202
	    $y1 = $ye;
203
	    $y0 = $this->rect->y;
204
	    while( $x0 <= $xe ) {
205
		$aImg->Line($x0,$y0,$x1,$y1);
206
		$x0 += $this->linespacing;
207
		$x1 += $this->linespacing;
208
	    }
209
 
210
	    $y0=$this->rect->y + ($x0-$xe);
211
	    $x0=$xe;
212
	}
213
	else {
214
	    // Height larger than width
215
	    $diff = $x0-$xe;
216
	    $y0 = $diff+$this->rect->y;
217
	    $x0 = $xe;
218
	    $x1 = $this->rect->x;
219
	    while( $y1 <= $ye ) {
220
		$aImg->Line($x0,$y0,$x1,$y1);
221
		$y1 += $this->linespacing;
222
		$y0 += $this->linespacing;
223
	    }
224
 
225
	    $diff = $y1-$ye;
226
	    $y1 = $ye;
227
	    $x1 = $diff + $this->rect->x;
228
	}
229
 
230
	while( $y0 <= $ye ) {
231
	    $aImg->Line($x0,$y0,$x1,$y1);
232
	    $y0 += $this->linespacing;
233
	    $x1 += $this->linespacing;
234
	}
235
    }
236
}
237
 
238
//=====================================================================
239
// Class RectPatternLDiag
240
// Implements left diagonal pattern
241
//=====================================================================
242
class RectPatternLDiag extends RectPattern {
243
    var $linespacing;	// Line spacing in pixels
244
 
245
    function RectPatternLDiag($aColor="black",$aWeight=1,$aLineSpacing=12) {
246
	$this->linespacing = $aLineSpacing;
247
	parent::RectPattern($aColor,$aWeight);
248
    }
249
 
250
    function DoPattern(&$aImg) {
251
	//  --------------------
252
	//  |\   \   \   \   \ |
253
	//  | \   \   \   \   \|
254
	//  |  \   \   \   \   |
255
	//  |------------------|
256
	$xe = $this->rect->xe;
257
	$ye = $this->rect->ye;
258
	$x0 = $this->rect->x + round($this->linespacing/2);
259
	$y0 = $this->rect->ye;
260
	$x1 = $this->rect->x;
261
	$y1 = $this->rect->ye - round($this->linespacing/2);
262
 
263
	while($x0<=$xe && $y1>=$this->rect->y) {
264
	    $aImg->Line($x0,$y0,$x1,$y1);
265
	    $x0 += $this->linespacing;
266
	    $y1 -= $this->linespacing;
267
	}
268
	if( $xe-$x1 > $ye-$this->rect->y ) {
269
	    // Width larger than height
270
	    $x1 = $this->rect->x + ($this->rect->y-$y1);
271
	    $y0=$ye; $y1=$this->rect->y;
272
	    while( $x0 <= $xe ) {
273
		$aImg->Line($x0,$y0,$x1,$y1);
274
		$x0 += $this->linespacing;
275
		$x1 += $this->linespacing;
276
	    }
277
 
278
	    $y0=$this->rect->ye - ($x0-$xe);
279
	    $x0=$xe;
280
	}
281
	else {
282
	    // Height larger than width
283
	    $diff = $x0-$xe;
284
	    $y0 = $ye-$diff;
285
	    $x0 = $xe;
286
	    while( $y1 >= $this->rect->y ) {
287
		$aImg->Line($x0,$y0,$x1,$y1);
288
		$y0 -= $this->linespacing;
289
		$y1 -= $this->linespacing;
290
	    }
291
	    $diff = $this->rect->y - $y1;
292
	    $x1 = $this->rect->x + $diff;
293
	    $y1 = $this->rect->y;
294
	}
295
	while( $y0 >= $this->rect->y ) {
296
	    $aImg->Line($x0,$y0,$x1,$y1);
297
	    $y0 -= $this->linespacing;
298
	    $x1 += $this->linespacing;
299
	}
300
    }
301
}
302
 
303
//=====================================================================
304
// Class RectPattern3DPlane
305
// Implements "3D" plane pattern
306
//=====================================================================
307
class RectPattern3DPlane extends RectPattern {
308
    var $alpha=50;  // Parameter that specifies the distance
309
    // to "simulated" horizon in pixel from the
310
    // top of the band. Specifies how fast the lines
311
    // converge.
312
 
313
    function RectPattern3DPlane($aColor="black",$aWeight=1) {
314
	parent::RectPattern($aColor,$aWeight);
315
	$this->SetDensity(10);  // Slightly larger default
316
    }
317
 
318
    function SetHorizon($aHorizon) {
319
	$this->alpha=$aHorizon;
320
    }
321
 
322
    function DoPattern(&$aImg) {
323
	// "Fake" a nice 3D grid-effect.
324
	$x0 = $this->rect->x + $this->rect->w/2;
325
	$y0 = $this->rect->y;
326
	$x1 = $x0;
327
	$y1 = $this->rect->ye;
328
	$x0_right = $x0;
329
	$x1_right = $x1;
330
 
331
	// BTW "apa" means monkey in Swedish but is really a shortform for
332
	// "alpha+a" which was the labels I used on paper when I derived the
333
	// geometric to get the 3D perspective right.
334
	// $apa is the height of the bounding rectangle plus the distance to the
335
	// artifical horizon (alpha)
336
	$apa = $this->rect->h + $this->alpha;
337
 
338
	// Three cases and three loops
339
	// 1) The endpoint of the line ends on the bottom line
340
	// 2) The endpoint ends on the side
341
	// 3) Horizontal lines
342
 
343
	// Endpoint falls on bottom line
344
	$middle=$this->rect->x + $this->rect->w/2;
345
	$dist=$this->linespacing;
346
	$factor=$this->alpha /($apa);
347
	while($x1>$this->rect->x) {
348
	    $aImg->Line($x0,$y0,$x1,$y1);
349
	    $aImg->Line($x0_right,$y0,$x1_right,$y1);
350
	    $x1 = $middle - $dist;
351
	    $x0 = $middle - $dist * $factor;
352
	    $x1_right = $middle + $dist;
353
	    $x0_right =  $middle + $dist * $factor;
354
	    $dist += $this->linespacing;
355
	}
356
 
357
	// Endpoint falls on sides
358
	$dist -= $this->linespacing;
359
	$d=$this->rect->w/2;
360
	$c = $apa - $d*$apa/$dist;
361
	while( $x0>$this->rect->x ) {
362
	    $aImg->Line($x0,$y0,$this->rect->x,$this->rect->ye-$c);
363
	    $aImg->Line($x0_right,$y0,$this->rect->xe,$this->rect->ye-$c);
364
	    $dist += $this->linespacing;
365
	    $x0 = $middle - $dist * $factor;
366
	    $x1 = $middle - $dist;
367
	    $x0_right =  $middle + $dist * $factor;
368
	    $c = $apa - $d*$apa/$dist;
369
	}
370
 
371
	// Horizontal lines
372
	// They need some serious consideration since they are a function
373
	// of perspective depth (alpha) and density (linespacing)
374
	$x0=$this->rect->x;
375
	$x1=$this->rect->xe;
376
	$y=$this->rect->ye;
377
 
378
	// The first line is drawn directly. Makes the loop below slightly
379
	// more readable.
380
	$aImg->Line($x0,$y,$x1,$y);
381
	$hls = $this->linespacing;
382
 
383
	// A correction factor for vertical "brick" line spacing to account for
384
	// a) the difference in number of pixels hor vs vert
385
	// b) visual apperance to make the first layer of "bricks" look more
386
	// square.
387
	$vls = $this->linespacing*0.6;
388
 
389
	$ds = $hls*($apa-$vls)/$apa;
390
	// Get the slope for the "perspective line" going from bottom right
391
	// corner to top left corner of the "first" brick.
392
 
393
	// Uncomment the following lines if you want to get a visual understanding
394
	// of what this helpline does. BTW this mimics the way you would get the
395
	// perspective right when drawing on paper.
396
	/*
397
	  $x0 = $middle;
398
	  $y0 = $this->rect->ye;
399
	  $len=floor(($this->rect->ye-$this->rect->y)/$vls);
400
	  $x1 = $middle+round($len*$ds);
401
	  $y1 = $this->rect->ye-$len*$vls;
402
	  $aImg->PushColor("red");
403
	  $aImg->Line($x0,$y0,$x1,$y1);
404
	  $aImg->PopColor();
405
	*/
406
 
407
	$y -= $vls;
408
	$k=($this->rect->ye-($this->rect->ye-$vls))/($middle-($middle-$ds));
409
	$dist = $hls;
410
	while( $y>$this->rect->y ) {
411
	    $aImg->Line($this->rect->x,$y,$this->rect->xe,$y);
412
	    $adj = $k*$dist/(1+$dist*$k/$apa);
413
	    if( $adj < 2 ) $adj=1;
414
	    $y = $this->rect->ye - round($adj);
415
	    $dist += $hls;
416
	}
417
    }
418
}
419
 
420
//=====================================================================
421
// Class RectPatternCross
422
// Vert/Hor crosses
423
//=====================================================================
424
class RectPatternCross extends RectPattern {
425
    var $vert=null;
426
    var $hor=null;
427
    function RectPatternCross($aColor="black",$aWeight=1) {
428
	parent::RectPattern($aColor,$aWeight);
429
	$this->vert = new RectPatternVert($aColor,$aWeight);
430
	$this->hor  = new RectPatternHor($aColor,$aWeight);
431
    }
432
 
433
    function SetOrder($aDepth) {
434
	$this->vert->SetOrder($aDepth);
435
	$this->hor->SetOrder($aDepth);
436
    }
437
 
438
    function SetPos(&$aRect) {
439
	parent::SetPos($aRect);
440
	$this->vert->SetPos($aRect);
441
	$this->hor->SetPos($aRect);
442
    }
443
 
444
    function SetDensity($aDens) {
445
	$this->vert->SetDensity($aDens);
446
	$this->hor->SetDensity($aDens);
447
    }
448
 
449
    function DoPattern(&$aImg) {
450
	$this->vert->DoPattern($aImg);
451
	$this->hor->DoPattern($aImg);
452
    }
453
}
454
 
455
//=====================================================================
456
// Class RectPatternDiagCross
457
// Vert/Hor crosses
458
//=====================================================================
459
 
460
class RectPatternDiagCross extends RectPattern {
461
    var $left=null;
462
    var $right=null;
463
    function RectPatternDiagCross($aColor="black",$aWeight=1) {
464
	parent::RectPattern($aColor,$aWeight);
465
	$this->right = new RectPatternRDiag($aColor,$aWeight);
466
	$this->left  = new RectPatternLDiag($aColor,$aWeight);
467
    }
468
 
469
    function SetOrder($aDepth) {
470
	$this->left->SetOrder($aDepth);
471
	$this->right->SetOrder($aDepth);
472
    }
473
 
474
    function SetPos(&$aRect) {
475
	parent::SetPos($aRect);
476
	$this->left->SetPos($aRect);
477
	$this->right->SetPos($aRect);
478
    }
479
 
480
    function SetDensity($aDens) {
481
	$this->left->SetDensity($aDens);
482
	$this->right->SetDensity($aDens);
483
    }
484
 
485
    function DoPattern(&$aImg) {
486
	$this->left->DoPattern($aImg);
487
	$this->right->DoPattern($aImg);
488
    }
489
 
490
}
491
 
492
//=====================================================================
493
// Class RectPatternFactory
494
// Factory class for rectangular pattern
495
//=====================================================================
496
class RectPatternFactory {
497
    function RectPatternFactory() {
498
	// Empty
499
    }
500
    function Create($aPattern,$aColor,$aWeight=1) {
501
	switch($aPattern) {
502
	    case BAND_RDIAG:
503
		$obj =  new RectPatternRDiag($aColor,$aWeight);
504
		break;
505
	    case BAND_LDIAG:
506
		$obj =  new RectPatternLDiag($aColor,$aWeight);
507
		break;
508
	    case BAND_SOLID:
509
		$obj =  new RectPatternSolid($aColor,$aWeight);
510
		break;
511
	    case BAND_VLINE:
512
		$obj =  new RectPatternVert($aColor,$aWeight);
513
		break;
514
	    case BAND_HLINE:
515
		$obj =  new RectPatternHor($aColor,$aWeight);
516
		break;
517
	    case BAND_3DPLANE:
518
		$obj =  new RectPattern3DPlane($aColor,$aWeight);
519
		break;
520
	    case BAND_HVCROSS:
521
		$obj =  new RectPatternCross($aColor,$aWeight);
522
		break;
523
	    case BAND_DIAGCROSS:
524
		$obj =  new RectPatternDiagCross($aColor,$aWeight);
525
		break;
526
	    default:
527
		JpGraphError::RaiseL(16003,$aPattern);
528
//(" Unknown pattern specification ($aPattern)");
529
	}
530
	return $obj;
531
    }
532
}
533
 
534
 
535
//=====================================================================
536
// Class PlotBand
537
// Factory class which is used by the client.
538
// It is responsible for factoring the corresponding pattern
539
// concrete class.
540
//=====================================================================
541
class PlotBand {
542
    var $prect=null;
543
    var $depth;
544
    var $dir, $min, $max;
545
 
546
    function PlotBand($aDir,$aPattern,$aMin,$aMax,$aColor="black",$aWeight=1,$aDepth=DEPTH_BACK) {
547
	$f =  new RectPatternFactory();
548
	$this->prect = $f->Create($aPattern,$aColor,$aWeight);
549
	if( is_numeric($aMin) && is_numeric($aMax) && ($aMin > $aMax) )
550
	    JpGraphError::RaiseL(16004);
551
//('Min value for plotband is larger than specified max value. Please correct.');
552
	$this->dir = $aDir;
553
	$this->min = $aMin;
554
	$this->max = $aMax;
555
	$this->depth=$aDepth;
556
    }
557
 
558
    // Set position. aRect contains absolute image coordinates
559
    function SetPos(&$aRect) {
560
	assert( $this->prect != null ) ;
561
	$this->prect->SetPos($aRect);
562
    }
563
 
564
    function ShowFrame($aFlag=true) {
565
	$this->prect->ShowFrame($aFlag);
566
    }
567
 
568
    // Set z-order. In front of pplot or in the back
569
    function SetOrder($aDepth) {
570
	$this->depth=$aDepth;
571
    }
572
 
573
    function SetDensity($aDens) {
574
	$this->prect->SetDensity($aDens);
575
    }
576
 
577
    function GetDir() {
578
	return $this->dir;
579
    }
580
 
581
    function GetMin() {
582
	return $this->min;
583
    }
584
 
585
    function GetMax() {
586
	return $this->max;
587
    }
588
 
589
    // Display band
590
    function Stroke(&$aImg,&$aXScale,&$aYScale) {
591
	assert( $this->prect != null ) ;
592
	if( $this->dir == HORIZONTAL ) {
593
	    if( $this->min === 'min' ) $this->min = $aYScale->GetMinVal();
594
	    if( $this->max === 'max' ) $this->max = $aYScale->GetMaxVal();
595
 
596
            // Only draw the bar if it actually appears in the range
597
            if ($this->min < $aYScale->GetMaxVal() && $this->max > $aYScale->GetMinVal()) {
598
 
599
	    // Trucate to limit of axis
600
	    $this->min = max($this->min, $aYScale->GetMinVal());
601
	    $this->max = min($this->max, $aYScale->GetMaxVal());
602
 
603
	    $x=$aXScale->scale_abs[0];
604
	    $y=$aYScale->Translate($this->max);
605
	    $width=$aXScale->scale_abs[1]-$aXScale->scale_abs[0]+1;
606
	    $height=abs($y-$aYScale->Translate($this->min))+1;
607
	    $this->prect->SetPos(new Rectangle($x,$y,$width,$height));
608
	    $this->prect->Stroke($aImg);
609
            }
610
	}
611
	else {	// VERTICAL
612
	    if( $this->min === 'min' ) $this->min = $aXScale->GetMinVal();
613
	    if( $this->max === 'max' ) $this->max = $aXScale->GetMaxVal();
614
 
615
            // Only draw the bar if it actually appears in the range
616
	    if ($this->min < $aXScale->GetMaxVal() && $this->max > $aXScale->GetMinVal()) {
617
 
618
	    // Trucate to limit of axis
619
	    $this->min = max($this->min, $aXScale->GetMinVal());
620
	    $this->max = min($this->max, $aXScale->GetMaxVal());
621
 
622
	    $y=$aYScale->scale_abs[1];
623
	    $x=$aXScale->Translate($this->min);
624
	    $height=abs($aYScale->scale_abs[1]-$aYScale->scale_abs[0]);
625
	    $width=abs($x-$aXScale->Translate($this->max));
626
	    $this->prect->SetPos(new Rectangle($x,$y,$width,$height));
627
	    $this->prect->Stroke($aImg);
628
            }
629
	}
630
    }
631
}
632
 
633
 
634
?>