Need nice way to create parabolic trajectory

Started by
10 comments, last by meteors 16 years, 10 months ago
Ill have a go at walking through the mathematics although I've posted code at the bottom if you just want to skip to that.
My approach seems a bit drawn out for what is really a simple problem, I'd be interested to see how anyone else does it?

Okay,
You have an origin point (x0, y0, z0) and a destination point (x1, y1, z1) and an angle we'll call theta.

The curve function
The curve itself lies on a plane that coincides with our origin point and destination point, I will use axes called w and y, where w lies arbitrarily along the xz-plane and y is the conventional 'up' axis. The planes origin maybe translated horizontally from world-space so that the origin is (x0, 0, z0).

The general equation of the curve is

y = Aw^2 + Bw + C

Where A,B,C are three unknowns that we must resolve.

We can tell from inspection that when w=0 then y = C, and that y must also equal y0 (the origin's y-component). So, obviously C = y0.

This leaves us with only A and B to resolve.

The differential of this curve is therefore

dy/dw = 2Aw + B

From the angle of the curve we know that when w=0 the gradient of the curve must equal TAN(theta) (I'm capitalising the tan to avoid confusion with t which I will introduce later on).

So:

dy/dw = TAN(theta) when w=0

therefore: B = TAN(theta)

So now we also have B, only A to go [smile]
We know that our curve has a single turning point and at this point its gradient is zero, some value for w will produce this point, lets call this value m.
Substituting in what we know for B and m inplace of w we have

2Am + TAN(theta) = 0

Rearranging to get A

A = -TAN(theta) / 2m

So we have A although its in terms of yet another unknown, m, but thats OK, we can substitute A, B and C into our curves general equation:

y = (w^2)(-TAN(theta)/(2m)) + (w)TAN(theta) + y0

We need to resolve m, but thats more complicated.
If we know a position on our current curve function (y = f(w)) then we could substitute that in and get m.
Luckily we know that our destination point lies somewhere on our curve, we can find its position on our wy-plane as so:

w = sqrt((x1-x0)^2 + (y1-yo)^2))
y = y1

Conceptually sqrt((x1-x0)^2 + (y1-yo)^2)) is the horizontal distance of the curve, since its a-lot to type I will assign it to an alias and call it L, therefore w = L.

Substituting these in:

y1 = (-TAN(theta)/(2m))(L^2) + (L)TAN(theta) + y0

we can now rearrange to get m, although actually we need only go as far as -1/(2m)

-1/(2m) = ((y1-y0)/TAN(theta) - L) / (L^2)

And now we must substitute this back into the general equation (the one in bold-italics):

y = (w^2)TAN(theta)(((y1-y0)/TAN(theta) - L) / (L^2)) + (w)TAN(theta) + y0

At this point we can simplify the w^2 coefficients:

y = (w^2)(((y1-y0) - (L)TAN(theta)) / (L^2)) + (w)TAN(theta) + y0

Now we have the working function: y = f(w), where w is between 0 and L.

Ideally we would have a parametric function: y = f(t), where t is between 0 and 1

Its not hard to see that with the relationship w = tL then f(w) = f(tL)

So substituting tL inplace of w we get:

y = ((tL)^2)(((y1-y0) - (L)TAN(theta)) / (L^2)) + (tL)TAN(theta) + y0

The L^2 terms cancel out and we can multiply through with the t^2 term:

y = (t^2)(y1-y0) - (t^2)(L)TAN(theta) + (tL)TAN(theta) + y0

Now factorise out (tL)TAN(theta)

y = (tL)(1-t)TAN(theta) + (t^2)(y1-y0) + y0

And so finally we now have something of the form: y = f(t) [smile]

Now the x and z axes
The x and z axes are much easier to calculate.
We want functions, g and h such that:

x = g(t)
z = h(t)

Where t is in the range 0 to 1.

Both functions take the form:

p = o + t(d - o)

where p is the output position (x or z), o is the origin component and d is the destination component.

Therefore:

x = x0 + t(x1 - x0)
z = z0 + t(z1 - z0)


Now we've done the maths, lets see some code
As TheAdmiral rightly pointed out you will be needing a fourth parameter in your function definition, this is the t parameter, its in the range 0 to 1 so it needs to be floating point (float or double in C/C++ terms).

With that said, here's your function (though untested):
Vector3 calculateTrajectory(Vector3 origin, Vector3 destination, double angle, float t){    Vector3 output;    // Just for convenience    float xDisplacement = (destination.x - origin.x);    float yDisplacement = (destination.y - origin.y);    float zDisplacement = (destination.z - origin.z);    float tanTheta      = std::tan(angle);    // Calculate the x and z components    output.x = origin.x + t * xDisplacement;    output.z = origin.z + t * zDisplacement;    // Calculate the horizontal distance covered by our curve    float distance = std::sqrt(xDisplacement*xDisplacement + zDisplacement*zDisplacement);    // Calculate the y component    output.y = (t*distance*(1-t)*tanTheta) + (t*t * yDisplacement) + origin.y;    return output;}

Note that this function expects the angle in radians, if you desire degrees then you can convert using:

radians = degrees/180*pi


Well yes that was a very long post, but I found it interesting to write anyway [smile], my proof-reading is usually not brilliant but with any luck it makes sense.

Hope that was some help anyway
Have a nice day

David

[Edited by - dmatter on June 30, 2007 12:37:25 PM]
Advertisement
Ok guys, I need a day to digest all this.

Thank you!!!! ...and I'll post more shortly.



All the best,
-joshua

This topic is closed to new replies.

Advertisement