histogram: Make histograms crash less
[ninja.git] / application / vendor / mfchart / CurvedLinePointChart.php
blobcf8e105d2fb5b2768f778cb8bbcbe4b2cd54a074
1 <?php
3 class CurvedLinePointChart extends LinePointChart {
5 protected $shaded = TRUE;
8 public function __construct($width=NULL, $height=NULL)
10 parent::__construct($width, $height);
12 $this->type = 'curved';
15 public function set_shaded($value)
17 $this->shaded = $value;
21 protected function draw_values($zeroline, $ratio)
23 $plot_sizes = $this->get_plot_area();
24 $font_point_legend = $this->font_size < 1 ? $this->font_size : $this->font_size-1;
26 $total_groups = count($this->values); // count of all groups of points
27 $gap = ($plot_sizes[0] - $total_groups) / ($total_groups+1); // gap between points
29 // -- compute positions of points of lines
31 $lines = array();
33 $i=0;
34 foreach ($this->values AS $key => $v)
36 $x = $this->margin_left + $gap + 1 + $i*($gap+1); // 1 is considered as point width
37 $y2 = $this->height - $this->margin_bottom - $zeroline;
39 foreach ($v as $j => $value)
41 $y = $y2 - $value*$ratio;
42 $lines[$j][] = array($x, $y, $value);
45 if ($this->vertical_point_lines)
46 imageline($this->image, $x, $this->margin_top-1, $x, $this->height-$this->margin_bottom-1, IMG_COLOR_STYLED);
48 $box_points = imagettfbbox($this->font_size, 0, $this->font, $key);
49 $y_legend_hwidth = ($box_points[4]-$box_points[6]) / 2;
50 $fheight = $box_points[3]-$box_points[5];
52 // x axis legend
53 utilities::imagestringbox($this->image, $this->font, $this->font_size, $x-$y_legend_hwidth, $this->margin_top+$plot_sizes[1]+5, $x+$y_legend_hwidth, $this->margin_top+$plot_sizes[1]+5+$fheight, ALIGN_CENTER, VALIGN_MIDDLE, 0, $key, $this->get_color('font_color'));
55 $i++;
58 // -- draw lines
60 // $dark = imagecolorallocatealpha($this->image, 49, 49, 49, 95);
61 // $dark2 = imagecolorallocatealpha($this->image, 140, 140, 140, 95);
62 // $dark3 = imagecolorallocatealpha($this->image, 200, 200, 200, 95);
64 foreach ($lines as $i => $line)
66 $color = utilities::hex2rgb($this->get_color('pen_color', $i, 0));
68 if (count($line) < 3) // for curved chart we need at least 3 points
69 { // classic
70 for ($j=0; $j<count($line)-1; $j++)
71 utilities::imagesmoothline($this->image, $line[$j][0], $line[$j][1], $line[$j+1][0], $line[$j+1][1], $color[0], $color[1], $color[2], $this->pen_width);
73 else
74 { // curved
75 $z = $this->cubic_interpolation_z($line);
77 $first_node = $line[0][0];
78 $last_node = $line[count($line)-1][0];
79 $previous = array($line[0][0], $line[0][1]);
80 for ($x=$first_node; $x<=$last_node; $x++)
82 $y = $this->cubic_interpolation_s($x, $line, $z);
83 if ($this->shaded)
84 { // draw shade
85 // imageline($this->image, $previous[0], $previous[1]+$this->pen_width-1, $x, $y+$this->pen_width-1, $dark);
86 // imageline($this->image, $previous[0], $previous[1]+$this->pen_width, $x, $y+$this->pen_width, $dark2);
87 // imageline($this->image, $previous[0], $previous[1]+$this->pen_width+1, $x, $y+$this->pen_width+1, $dark3);
88 utilities::imagesmoothalphaline($this->image, $previous[0], $previous[1]+$this->pen_width-1, $x, $y+$this->pen_width-1, 49, 49, 49, 95);
89 utilities::imagesmoothalphaline($this->image, $previous[0], $previous[1]+$this->pen_width, $x, $y+$this->pen_width, 140, 140, 140, 95);
90 utilities::imagesmoothalphaline($this->image, $previous[0], $previous[1]+$this->pen_width+1, $x, $y+$this->pen_width+1, 140, 140, 140, 95);
91 utilities::imagesmoothalphaline($this->image, $previous[0], $previous[1]+$this->pen_width+2, $x, $y+$this->pen_width+2, 200, 200, 200, 95);
94 // imagesetthickness($this->image, $this->pen_width);
95 // imageline($this->image, $previous[0], $previous[1], $x, $y, $this->get_color('pen_color', $i));
96 // imagesetthickness($this->image, 1);
98 utilities::imagesmoothline($this->image, $previous[0], $previous[1], $x, $y, $color[0], $color[1], $color[2], $this->pen_width);
100 $previous = array($x, $y);
104 foreach ($line as $point)
106 $this->draw_point($point[0], $point[1], $this->point_style, $this->get_color('point_color', $i), $this->get_color('point_fill_color', $i));
108 $box_points = imagettfbbox($this->font_size, 0, $this->font, $value);
109 $point_legend_hwidth = ($box_points[4]-$box_points[6]) / 2;
110 $fheight = $box_points[3]-$box_points[5];
112 // point legend
113 if ($this->point_legend)
115 utilities::imagestringbox($this->image, $this->font, $font_point_legend, $point[0]-$point_legend_hwidth, $point[1]-$fheight-5-$this->point_width/2, $point[0]+$point_legend_hwidth, $point[1]-$this->point_width/2, ALIGN_CENTER, VALIGN_MIDDLE, 0, $point[2], $this->get_color('font_color3'));
116 $this->add_occupied($point[0]-$point_legend_hwidth, $point[1]-$fheight-5-$this->point_width/2, $point[0]+$point_legend_hwidth, $point[1]-$this->point_width/2);
122 function cubic_interpolation_z($points)
124 // find Zi
126 // compute Hi and Bi
127 $h = array();
128 $b = array();
129 for ($i=0; $i<count($points)-1; $i++)
131 $h[$i] = $points[$i+1][0]-$points[$i][0];
132 $b[$i] = ($points[$i+1][1]-$points[$i][1])/$h[$i];
135 // gaussian elimination
136 $u = array();
137 $v = array();
138 $u[1] = 2*($h[0]+$h[1]);
139 $v[1] = 6*($b[1]-$b[0]);
140 for ($i=2; $i<count($points)-1; $i++)
142 $u[$i] = 2*($h[$i-1]+$h[$i]) - pow($h[$i-1], 2)/$u[$i-1];
143 $v[$i] = 6*($b[$i]-$b[$i-1]) - $h[$i-1]*$v[$i-1]/$u[$i-1];
146 // back substitution
147 $z = array();
148 $z[count($points)-1] = 0;
149 for ($i=count($points)-2; $i>0; $i--)
151 $z[$i] = ($v[$i] - $h[$i]*$z[$i+1]) / $u[$i];
153 $z[0] = 0;
155 return $z;
158 function cubic_interpolation_s($x, $points, $z)
160 // find Si interval
161 for ($i=0; $i<count($points)-1; $i++)
162 if ($x <= $points[$i+1][0])
163 break;
165 $h = $points[$i+1][0]-$points[$i][0];
167 // compute a, b, c, d
168 $a = $points[$i][1];
169 $b = - ($h/6)*$z[$i+1] - ($h/3)*$z[$i] + ($points[$i+1][1]-$points[$i][1])/$h;
170 $c = $z[$i]/2;
171 $d = ($z[$i+1]-$z[$i])/(6*$h);
173 $e = $x-$points[$i][0];
175 return $a + $e*( $b+$e*( $c+$e*$d ) );