[Math] 2D – Coordinates of a point along a line, based on d and m – Where am I messing up

geometry

LATER EDIT:

I managed to find the errors in my equations below. It was a sign mistake on one of the terms (- instead of +). Having corrected that, the method which I describe below WORKS, but DON'T USE IT ::- D. My method is convoluted and prone to mistakes (as I proved, haha). The 2 answers below offer much better choices. hardmath found a few of my mistakes and provided an alternative way of obtaining X2 and Y2 using the same system of formulas I used.

On the other hand, joriki provided an alternate solution which is VERY efficient in terms of number of calculations which need to be done each frame. Eventually, I completely dropped my approach and will use his solution.

Thank you hardmath and joriki, and, by all means, Math @ Stack ::- D. You people rule! I humbly thank you for helping a programmer in distress!

ORIGINAL POST:

Hi ::- D. I'm working on a (Flash) game and I have a weapon from which a projectile departs. The projectile travels along a line. I have the slope of the line as well as the origin (1 point). I want to calculate, depending on the Distance, where should I draw the projectile, frame by frame. The distance increases with a certain quantity each frame, as the projectile travels along the line.

I have tried my best to solve this and this is what I did so far. I would not mind if you know a simpler way, but I would very much appreciate it if you would tell me why my method doesn't work (the coordinates I'm getting are very chaotic).

I used these equations to build a system:

http://www.analyzemath.com/Calculators/TwoPointsCalculator.html

d = sqrt [ (x1 -x2)^ + (y1 - y2)^ ]

m = (y2 - y1) / (x2 - x1)

I took out y2:

y2 = m * x2 - m * x1 + y1

From that equation, I know everything except x2. x1, y1 and m are all known. I'm out to find x2 and y2 which are the coordinates of my desired point.

I removed the radical by squaring the first equation and also breaking (solving) the paranthesis. I should mention it's been a very long time since I did any math so please excuse the lack of correct terminology. Also, I'm unfamiliar with how to produce a fast MathJaX of the equations, but I think they're simple enough to be written normally. ^ – means square. I used some extra paranthesis to clear it up.

d^ = x1^ - (2 * x2 * x1) + x2^ + y1^ - (2 * y2 * y1) + y2 ^

Ok so I also know who d is. Now, I took y2 and substituted it in the above equation. This is what resulted:

d^ = x1^ - 2 * x2 * x1  + x2^ + y1^ - 2 * y1 * (m * x2 + K) + (m * x2 +K) ^

Where K is that part which I can calculate from the above y2 equation: y2 = m* x2 -m * x1 + y1

So now I got an equation where I know everything except x2. I reduced this equation to a quadratic equation. The final form (I solved the squared parenthesis above as well) is:

x2^ ( - 1 - m^) + x2 (2 * x1   + 2 *  y1 * m - 2 * m * K) + d^ - x1^ - y1^ + 2 * y1 * K - K ^ = 0

Looks scary doesn't it? laugh.

This seems to be correct so far. Because we're talking about a line, slope and distance, it's obvious that there can be TWO points which are of distance D from my Origin (x1, y1). So I solve the quadratic equation in order to find x2-1 and x2-2 which I can then take to my first equation and get y2-1 and y2-2. So, I moved to solve the quadratic equation. First, I found a, b and c.

a = -1 - m^
b = (2 * x1   + 2 *  y1 * m - 2 * m * K) 
c = d^ -  x1^ - y1^  + 2 * y1 * K - K ^ 

And now, I found the 2 roots:

x2 = (-b + sqrt (b^ - 4ac)) / 2a
x2 = (-b - sqrt (b^ - 4ac)) / 2a

Then, I found the two y2 points. And that's it ::- D.

It doesn't work laugh……… I worked for hours this morning, flexing whatever pathetic math muscles I got left and I worked all this far to end up with:

(x=1509141.9643610462, y=20806970.245399687)

This, in a case where the origin is at 200, 250 and the distance is 1 and the slope is 2.2 or -0.7 or whatever…….

Sometimes, I even get NaN (that is, Not A Number, invalid value in ActionScript 3). So the values I'm getting are DEFINITELY not related to my origin.

A point of interest however: for slope = 1.380657160570366, my projectile ACTUALLY SEEMS TO WORK, as in, it appears a bit TOO far from the Origin (about 50 pixels), but it DOES MOVE along the correct line, albeit, strangely, it ACCELERATES, even though I never increase its speed, I simply increase the distance:

_ProjectileDistance += _ProjectileSpeed;
var newCoords: Point = GetPointAlongLine(weaponRootPointX, weaponRootPointY, _ProjectileDistance, _ProjectileSlope);
Projectile.x = newCoords.x;
Projectile.y = newCoords.y;

And for those who know programming as well, here is what all I said looks like in code:

  var a: Number = - 1 - slope * slope;
  var b: Number = 2 * x1 + 2 * y1 * slope - 2 * slope * y2KnownPart;
  var c: Number = distance*distance - x1*x1 - y1*y1 - 2 * y1 * y2KnownPart - y2KnownPart*y2KnownPart;

  var x2Root1: Number = (- b + Math.sqrt(b*b - 4 * a * c)) / (2 * a);
  var x2Root2: Number = (- b - Math.sqrt(b*b - 4 * a * c)) / (2 * a);
  var y2Root1: Number = slope * x2Root1 + y2KnownPart;
  var y2Root2: Number = slope * x2Root2 + y2KnownPart;

Sorry for the long post ::- D. I hope somebody will have the patience to read until this line ::- D. If you did, know that you're doing it for a good cause ::- D. My games are free, so is my software, just look here ::- D https://sourceforge.net/users/echysttas

Best Answer

Your approach is way too complicated -- I won't take the time to find where you made a mistake, but instead show how it can be done much simpler:

The distance $d$ is the hypotenuse of a right triangle formed by the two axis-parallel segments of lengths $\Delta y := y_2-y_1$ and $\Delta x := x_2-x_1$, much like in this picture I found on the web:

enter image description here
(source: sternenwind.ch)

The slope $m$ is $\Delta y/\Delta x$, which is the tangent of the angle $\alpha$ between the line and the $x$-axis: $m=\tan\alpha$. The increments $\Delta x$ and $\Delta y$ are given by the cosine and sine, respectively, of that angle times the hypotenuse, so all you have to do is calculate $\alpha=\arctan m$ and then $\Delta x = d\cos \alpha$ and $\Delta y=d\sin\alpha$. If your calculations are time-critical, you can get by with a couple fewer transcendental operations, but this is the most straightforward way.

Edit: Actually, you'll want to use the atan2 function that a lot of programming environments have, with arguments $\Delta y$ and $\Delta x$, since you lose a sign when you form $m=\Delta y/\Delta x$, i.e. you no longer know which direction along the line the projectile is travelling.

Edit: hardmath's answer is roughly what I had in mind when I said "If your calculations are time-critical, you can get by with a couple fewer transcendental operations". Note, however, that in both answers the transcendental operations have to be performed only once (a square root in hardmath's case, three trigonometric functions in my case), and then calculating the projectile's position for each $d$ only involves multiplications.