I have a bunch of x-y graphs given to me and I need to be able to transform them into some kind of data structure from which I will be able to get Y with X value.
The problem is, though that I have 4, at max 5 values of Y given to me, and my X values can range up to 9000. So the information I have is something of the form
Point # X Y
1 1000 100
2 3250 460
3 6000 320
4 6500 300
My idea initially was something like:
function getY($x){
$data[1000] = 100;
$data[3250] = 460;
$data[6000] = 320;
$data[6500] = 300;
if(isset($data[$x])){
return $data[$x];
}
$minKnown = null;
$maxKnown = null;
foreach($data as $_x => $y){
if($_x < $x){
$minKnown = $_x;
}
if($_x > $x){
$maxKnown = $_x;
break;
}
}
return $data[$minKnown] + (($x - $minKnown) / ($maxKnown - $minKnown)) * ($data[$maxKnown] - $data[$minKnown]);
}
}
This function I just wrote to illustrate my idea. Basically if a point is not defined but somewhere between 2 known points, assuming there are no curves between the two points get the value that co-responds to the position of X between the two known values of X. I’m not even sure if my verbal explanation is actually correct or not but I guess that’s what I wrote the function for.
Anyway, I was thinking, since graphs something that’s widely used, are there any better ways of doing this, and I’m hoping there are otherwise I might turn out to be smarter than I thought, which is scary.
1
Since you said, that you assume that there are no curves, the graph itself would probably look like a stock development. So I would try a vector calculation approach.
With the data you gave in your example you would get 3 vectors defined by two points. (To generalize it, you would get one vector less then you got points.)
In your example:
Vector1: Point1->Point2 (Point2[x] – Point1[x], Point2[y] – Point1[y])
Vector2: Point2->Point3 (Point3[x] – Point2[x], Point3[y] – Point2[y])
Vector3: Point3->Point4 (Point4[x] – Point3[x], Point4[y] – Point3[y])
With values:
Vector1: (3250 – 1000, 460 – 100) = (2250, 360)
Vector2: (6000 – 3250, 320 – 460) = (2750, -140)
Vector3: (6500 – 6000, 300 – 320) = (500, -20)
Now the standard linear function has the form y = m*x + b. The vector itself won’t need the b. So for Vector1 it is: 360 = m * 2250
Resolved for m we get: m = 360 / 2250 = 0.16
Now we get back to the original line between P1 and P2, which will require a value for b.
We get this now with: 100 = 0.16 * 1000 + b => b = -60
With that we know each y value between Point1 and Point2 will be defined by this equation: y = 0.16 * x – 60.
You can check this by simply inserting the values of one of the points into the equation:
P1 100 = 1000 * 0.16 – 60
P2 460 = 3250 * 0.16 – 60
Code example:
$vector1x = $Point2->X - $Point1->X;
$vector1y = $Point2->Y - $Point1->Y;
$m1 = $vector1y / $vector1x
$b1 = $Point1->y - $Point1->x * $m1
// do the same for the other points as described.
Now when you get a value for x which you want to get the y value of do sth like this:
function getY($x)
{
if($x >= $Point1->X && $x <= $Point2->X)
{
$y = $m1 * $x + $b1;
}
else if($x <= $Point3->X)
{
$y = $m2 * $x + $b2;
}
else if($x <= $Point4->X)
{
$y = $m3 * $x + $b3;
}
else
{
throw new Exception("Cannot calculate value with given data!");
}
return $y;
}
I hope this approach serves your needs and helps you in solving the problem.