How to write a function that is about intersecting (graph) functions?

Started by KyriakosCH, Thu 24/11/2022 09:33:47

Previous topic - Next topic

KyriakosCH

Hey :)
Listen, I will be immediately noting that up to now I never used any function in AGS - by which I mean nothing that wasn't composed of the basic elements used without formatting them explicitly as a "function".
But I had a game idea, and it would require answering correctly some stuff which (ultimately; it won't be phrased as such) are graphs of functions-related. Intersecting point(s) of two graphs is one of them.
And because a) I am not familiar with the AGS function-writing system, and b) it would really suck if I didn't at least ask for something specific, let's ask how you would write a function for the following:

Check if the numerical input (corresponds to coordinates x,y) is correct for the point where f(x)=ax^2+c and f(x)=b(ax)+d intersect (if needed, the constants can be removed, and I don't mind a single-digit limitation on the (integer anyway) coefficients either; nor do I care for larger exponents than 2)
This is the Way - A dark allegory. My Twitter!  My Youtube!

Snarky

Off the top of my head, given the coordinates (x1,y1) and two functions f(x) and g(x), I think the easiest way would be to calculate the values of f(x) and g(x) at x1. If both equal y1, then you have found an intersection point between them.

If the form of f(x) and g(x) are fixed, so that f(x) is always a quadratic curve and g(x) always a line, you can easily do this check in a single AGS function. Just enter the parameters and coordinates as function arguments, calculate the function values, and compare the results. If the form of the curves can vary arbitrarily, I would probably break up the logic into sub-functions.

It would look something like this:

Code: ags
bool isIntersection(int a, int c, int b, int d, int x1, int y1)
{
  int f_x1 = a*x1*x1 + c;
  int g_x1 = a*b*x1 + d;
  return (f_x1 == y && g_x1 == y1);
}

This approach allows you to easily add in a tolerance for the y value, but if you also want some tolerance in x, you'll need to actually solve the equations.

Edit: Just noticed that you talk about digits in the parameters, so presumably you'd want those as floats. Then it gets a little bit more work, since you can't just do a == comparison, since floats are not exact.

KyriakosCH

Shows that what I said was true - never used the function system, and the above reveals you can have many bits that are combined, in memory for the same function.
And yes, for the time being I see no reason to go further than exponent 2 for one function and linear for the other.
But - why not ^^ - would AGS code allow for also calculating (through slope; which you can just set up another function to calculate on account of the power rule) the angle of meeting points of the (say) quadratic and linear graphs?

Oh, and thank you :D

Quote from: Snarky on Thu 24/11/2022 09:54:13Edit: Just noticed that you talk about digits in the parameters, so presumably you'd want those as floats. Then it gets a little bit more work, since you can't just do a == comparison, since floats are not exact.

This is how I imagine it: the game comes up with arbitrary coefficients and constants (within reason, say single digit numbers 1-9), and calculates the correct answer, then the player is prompted to give the correct answer (enter x,y for the intersection)
This is the Way - A dark allegory. My Twitter!  My Youtube!

Snarky

#3
Quote from: KyriakosCH on Thu 24/11/2022 10:06:10This is how I imagine it: the game comes up with arbitrary coefficients and constants (within reason, say single digit numbers 1-9), and calculates the correct answer, then the player is prompted to give the correct answer (enter x,y for the intersection)

OK, so the intersection points may not be at integer coordinates. That means we need to use floats. The problem is that floats are not exact, so we have to use rounding. And you can in theory have the curve and line come very close without intersecting (or before they intersect), so just checking that we are "close" to both curves is not good enough.

In that case, I think the best solution is to solve the equation for the intersection points (if any) using the quadratic formula, and then compare those coordinates to the input coordinates. If they are within tolerance (identical up to some number of significant digits), it's a match.

You can use a function like:

Code: ags
// Find the roots of the quadratic equation ax^2 + bx + c == 0
float[] quadraticRoots(float a, float b, float c)
{
  float discriminant = b*b - 4*a*c;
  if(discriminant < 0.0)
    return null; // no real roots

  // Else, for simplicity, we always return two roots, even if identical
  float[] roots = new float[2];
  float stable = -b / (2.0*a);
  float variant = Maths.Sqrt(discriminant/(4.0*a*a));
  roots[0] = stable - variant;
  roots[1] = stable + variant;
  return roots;
}

// Just a helper function for when coefficients are all ints
float[] quadraticRootsInt(int a, int b, int c)
{
  return quadraticRoots(IntToFloat(a), IntToFloat(b), IntToFloat(c));
}

(Since we need to return two numbers, we create and return an array.)

So you just plug the difference in coefficients into the function to find the roots, which are the x-coordinates of the intersections, calculate the y-coordinates of one of the functions at those x-coordinates, and compare each pair of coordinates to the input to see if they match (to within some tolerance).

Quote from: KyriakosCH on Thu 24/11/2022 10:06:10But - why not ^^ - would AGS code allow for also calculating (through slope; which you can just set up another function to calculate on account of the power rule) the angle of meeting points of the (say) quadratic and linear graphs?

I assume you mean the slope of the quadratic curve at the point of intersection? Sure. Any basic mathematical formula can easily be calculated in AGS. I expect you'll be able to write that function yourself given the examples shown here.

Khris

Intersecting a quadratic and a linear function is done by equating the y value:

ax² + bx + c = dx + e
ax² + (b-d)x + (c-e) = 0


This way we're back at determining the roots of a quadratic equation.

Once you have the x coordinate, the slope of the quadratic equation is given by the first derivative:

2ax + b

Just insert the intersection point's x coordinate and you have the slope.
The linear equation's slope is d.

The angle between can be determined via the dot product. The slope is the y difference provided we move 1 unit to the right on the x axis, so we can use that to make a vector: the vector is simply (1;s) where s is the slope. We have to normalize this vector by dividing both 1 and s by the square root of s²+1.

Example: the slope is 2, so the vector is (1;2). Its length is the square root of 5, and if we divide both coefficients by that we get a unit vector of (0.4472; 0.8944).

Once we have the vectors x1;y1 and x2;y2 for both slopes, the dot product is x1*x2 + y1*y2. Plug that into Maths.ArcCos() and you have the angle.

KyriakosCH

Got to say, guys, I am very impressed by the already built functions in AGS (maths.arccos, really? excellent...), and again this reveals that I should have examined the function abilities in AGS...
Anyway, thanks a lot, and this is all exactly what I needed :D
Next you'll be telling me there is already a function in AGS set up to do Taylor series ^^
This is the Way - A dark allegory. My Twitter!  My Youtube!

SMF spam blocked by CleanTalk