2 /*=======================================================================
3 // File: JPGRAPH_REGSTAT.PHP
4 // Description: Regression and statistical analysis helper classes
6 // Author: Johan Persson (johanp@aditus.nu)
7 // Ver: $Id: jpgraph_regstat.php,v 1.1 2006/07/07 13:37:14 powles Exp $
9 // Copyright (c) Aditus Consulting. All rights reserved.
10 //========================================================================
13 //------------------------------------------------------------------------
15 // Create a new data array from an existing data array but with more points.
16 // The new points are interpolated using a cubic spline algorithm
17 //------------------------------------------------------------------------
19 // 3:rd degree polynom approximation
21 var $xdata,$ydata; // Data vectors
22 var $y2; // 2:nd derivate of ydata
25 function Spline($xdata,$ydata) {
27 $this->xdata
= $xdata;
28 $this->ydata
= $ydata;
32 if( $this->n
!== count($xdata) ) {
33 JpGraphError
::RaiseL(19001);
34 //('Spline: Number of X and Y coordinates must be the same');
37 // Natural spline 2:derivate == 0 at endpoints
39 $this->y2
[$n-1] = 0.0;
42 // Calculate 2:nd derivate
43 for($i=1; $i < $n-1; ++
$i) {
44 $d = ($xdata[$i+
1]-$xdata[$i-1]);
46 JpGraphError
::RaiseL(19002);
47 //('Invalid input data for spline. Two or more consecutive input X-values are equal. Each input X-value must differ since from a mathematical point of view it must be a one-to-one mapping, i.e. each X-value must correspond to exactly one Y-value.');
49 $s = ($xdata[$i]-$xdata[$i-1])/$d;
50 $p = $s*$this->y2
[$i-1]+
2.0;
51 $this->y2
[$i] = ($s-1.0)/$p;
52 $delta[$i] = ($ydata[$i+
1]-$ydata[$i])/($xdata[$i+
1]-$xdata[$i]) -
53 ($ydata[$i]-$ydata[$i-1])/($xdata[$i]-$xdata[$i-1]);
54 $delta[$i] = (6.0*$delta[$i]/($xdata[$i+
1]-$xdata[$i-1])-$s*$delta[$i-1])/$p;
57 // Backward substitution
58 for( $j=$n-2; $j >= 0; --$j ) {
59 $this->y2
[$j] = $this->y2
[$j]*$this->y2
[$j+
1] +
$delta[$j];
63 // Return the two new data vectors
64 function Get($num=50) {
66 $step = ($this->xdata
[$n-1]-$this->xdata
[0]) / ($num-1);
69 $xnew[0] = $this->xdata
[0];
70 $ynew[0] = $this->ydata
[0];
71 for( $j=1; $j < $num; ++
$j ) {
72 $xnew[$j] = $xnew[0]+
$j*$step;
73 $ynew[$j] = $this->Interpolate($xnew[$j]);
75 return array($xnew,$ynew);
78 // Return a single interpolated Y-value from an x value
79 function Interpolate($xpoint) {
84 // Binary search to find interval
85 while( $max-$min > 1 ) {
87 if( $this->xdata
[$k] > $xpoint )
93 // Each interval is interpolated by a 3:degree polynom function
94 $h = $this->xdata
[$max]-$this->xdata
[$min];
97 JpGraphError
::RaiseL(19002);
98 //('Invalid input data for spline. Two or more consecutive input X-values are equal. Each input X-value must differ since from a mathematical point of view it must be a one-to-one mapping, i.e. each X-value must correspond to exactly one Y-value.');
102 $a = ($this->xdata
[$max]-$xpoint)/$h;
103 $b = ($xpoint-$this->xdata
[$min])/$h;
104 return $a*$this->ydata
[$min]+
$b*$this->ydata
[$max]+
105 (($a*$a*$a-$a)*$this->y2
[$min]+
($b*$b*$b-$b)*$this->y2
[$max])*($h*$h)/6.0;
109 //------------------------------------------------------------------------
111 // Create a new data array from a number of control points
112 //------------------------------------------------------------------------
115 * @author Thomas Despoix, openXtrem company
116 * @license released under QPL
117 * @abstract Bezier interoplated point generation,
118 * computed from control points data sets, based on Paul Bourke algorithm :
119 * http://astronomy.swin.edu.au/~pbourke/curves/bezier/
121 var $datax = array();
122 var $datay = array();
125 function Bezier($datax, $datay, $attraction_factor = 1) {
126 // Adding control point multiple time will raise their attraction power over the curve
127 $this->n
= count($datax);
128 if( $this->n
!== count($datay) ) {
129 JpGraphError
::RaiseL(19003);
130 //('Bezier: Number of X and Y coordinates must be the same');
133 foreach($datax as $datumx) {
134 for ($i = 0; $i < $attraction_factor; $i++
) {
135 $this->datax
[$idx++
] = $datumx;
139 foreach($datay as $datumy) {
140 for ($i = 0; $i < $attraction_factor; $i++
) {
141 $this->datay
[$idx++
] = $datumy;
146 function Get($steps) {
149 for ($i = 0; $i < $steps; $i++
) {
150 list($datumx, $datumy) = $this->GetPoint((double) $i / (double) $steps);
155 $datax[] = end($this->datax
);
156 $datay[] = end($this->datay
);
158 return array($datax, $datay);
161 function GetPoint($mu) {
172 $munk = (double) pow(1-$mu,(double) $n);
174 for ($k = 0; $k <= $n; $k++
) {
178 $blend = $muk * $munk;
185 $blend /= (double) $kn;
189 $blend /= (double) $nkn;
193 $newx +
= $this->datax
[$k] * $blend;
194 $newy +
= $this->datay
[$k] * $blend;
197 return array($newx, $newy);