Take the 2-minute tour ×
Mathematics Stack Exchange is a question and answer site for people studying math at any level and professionals in related fields. It's 100% free, no registration required.

I'm working on a chapter in my book dealing with touch input, and my memory of high school trig (from circa 1988) is failing me. My search here has not yielded anything that I'm capable of applying to this particular problem.

Description

  • I have a ship on the screen. If the user touches the screen, I need to turn the ship to align with that point (but over several steps, so I'd do it in increments). To do this, I need to calculate the angle shown in the diagram below.

Knowns

  • The ship's current X and Y location.
  • The touch point's X and Y location

Can potentially calculate in case it helps

  • Arbitrary points along the line starting at the current location and going out to the current heading, given a distance.

  • Length of hypotenuse (I know the start and end points)

What I need to calculate

  • The Angle between the imaginary line which represents the current heading, and the touch point, with the vertex at the current location. This image shows what I'm looking for:

Need to solve for this angle

I've been searching all day for anything which will (ahem) trigger a memory as to how to solve this, but I've been hitting nothing useful. Trig was never a strong skill for me in any case.

Sin/Cos/Tan functions need more data than I currently have. I thought about doing something with line intersection to get the length of the opposite side so I could use the Sin function, but I couldn't figure out how to calculate the line perpendicular to the heading and passing through the known touch point.

I'll take anything which works, but I'm doing this calculation frequently, so efficiency (for things which can be represented in code) is a plus.

Thanks for your time here.

share|improve this question

4 Answers 4

up vote 3 down vote accepted

My answer is purely from a developer perspective (no mathematician here):

First find the difference between the end point and the start point:

var deltaX = touchPoint_x - shipCurrent_x;
var deltaY = touchPoint_y - shipCurrent_y;

Then get the angle in degrees:
var angle = Math.atan2(deltaY, deltaX) * 180 / PI;

I'm using javascript with CSS3 transform rotate, so I can rotate the "ship" to the desired angle.

You can check it out at: http://jsfiddle.net/dotnetricardo/W2VCu/17/

Hope it helps also! :)

share|improve this answer
    
Thanks :) So, it turns out I asked completely the wrong question. Your answer solved my problem (thanks!), but the other answers in this thread are the correct answers to the question I asked. If I could mark more than one as an answer, I would. FWIW, I had to do a little offsetting in my case because zero degrees is due north when working with my ship, but otherwise, this was it. –  Pete Dec 20 '12 at 4:52

I'm sorry I don't have the time to think about a full answer, because this is interesting and I have actually programmed things very similar to this, but I will try to help you.

You say at the end that another way to use trigonometric functions would be to know the length of the opposite side of the triangle. You can calculate it this way:

If you know the heading direction, you must be able to obtain a vector pointing in that direction from the ship, now, get a perpendicular one, which is, if the vector in the direction is (a b), the perpendicular is (-b a), (ovbiously they're ortogonal: a*(-b)+a*b=0). Now, with this and the touch point you can get a line perpendicular to the direction and that goes through the touch point. Having this you can solve the system of equations to get the intersection point of the 90º vertex of the triangle and calculate the opposite side, and you're done.

Probably doing it in a paper for a generic point helps, because it will get you a simple solution that you can programme right away.

Hope it helps.

share|improve this answer
    
Thank you for this information. –  Pete Dec 20 '12 at 5:06

Let your current location be $(x_c,y_c)$, your touch location be $(x_t,y_t)$. Since you can calculate arbitrary points along the line starting at the current location and going out to the current heading, given a distance, compute the point along the heading direction that is $1$ unit from $(x_c,y_c)$. Let us call this point $(x_a,y_a)$. Then you have the following $$\cos(\theta) = \dfrac{\left( x_t - x_c, y_t - y_c\right) \cdot \left( x_a - x_c, y_a - y_c\right)}{\sqrt{\left( x_t - x_c, y_t - y_c\right) \cdot \left( x_t - x_c, y_t - y_c\right)}}$$ where $\theta$ is the angle you are looking for and $a\cdot b$ denotes the inner product. i.e. $$\cos(\theta) = \dfrac{\left( x_t - x_c \right) \left( x_a - x_c \right)+ \left( y_t - y_c \right) \left( y_a - y_c \right)}{\sqrt{\left( x_t - x_c \right)^2 + \left( y_t - y_c\right)^2}}$$ In general, if $(x_a,y_a)$ is any arbitrary point, that is along the current heading direction but not necessarily $1$ unit away, then $$\cos(\theta) = \dfrac{\left( x_t - x_c, y_t - y_c\right) \cdot \left( x_a - x_c, y_a - y_c\right)}{\sqrt{\left( x_t - x_c \right)^2 + \left( y_t - y_c\right)^2}\sqrt{\left( x_a - x_c \right)^2 + \left( y_a - y_c \right)^2}}$$

EDIT

The above argument uses the fact that if we have two vectors $\vec{a}$ and $\vec{b}$, then $$\cos(\theta) = \dfrac{\vec{a} \cdot \vec{b}}{\Vert \vec{a} \Vert \Vert \vec{b} \Vert}$$ where $\vec{a} \cdot \vec{b}$ denotes the inner product of $\vec{a}$ and $\vec{b}$.

share|improve this answer
    
Thank you for this answer. –  Pete Dec 20 '12 at 4:55

You'll have to use the ship's current heading in some way. If the heading is given as a angle $\theta$ with respect to the positive $x$-axise, then we take the difference of $\theta$ and the angle corresponding to the touch point $(x,y)$. Assuming the lower-left corner of the screen is the origin, then

$$ \textrm{Angle} = \theta - \arctan\left(\frac{y}{x}\right)$$

If, on the other hand, you just have a second point along the heading of the ship, for example, the ship is located at $(a,b)$, but heading towards $(c,d)$, then use the fact that the dot product of two vectors is related to the angle formed between them. To be more precise, let $\mathbf{v} = (c-a, d-b)$ be the vector along the heading of the ship, and $\mathbf{w} = (x-a, y-b)$ be the vector from the ship to the touch point.

$$ \textrm{Angle} = \arccos \frac{ \mathbf{v}\cdot \mathbf{w} }{ ||\mathbf{v}||\, ||\mathbf{w}||} = \arccos\frac{ (c-a)(x-a)+(d-b)(y-b)}{\sqrt{((c-a)^2 + (d-b)^2)((x-a)^2 + (y-b)^2))}} $$

Hope this helps!

share|improve this answer
    
Thanks. 0,0 Origin is upper left corner of the screen (we always work in backwards coordinate systems). On the second part of your anwwer, do both v and w need to be normalized to 1, or otherwise related? IOW, if the length of vector w is something like 250, does it matter what the length of v is when I use it in this formula? –  Pete Dec 16 '12 at 21:44
    
Ok, I didn't necessarily want to assume the location of the origin, and I do now remember from my programming days that $(0,0)$ is located in the upper left. The beauty of this approach though, is that it works regardless of the location of the origin (except that angles are measured clockwise rather than counterclockwise). –  Shaun Ault Dec 16 '12 at 23:15
    
And, no, the vectors need not be normalized... In fact, if they were, then there would be no need for the denominator, as then $||\mathbf{v}|| =||\mathbf{w}|| = 1$. –  Shaun Ault Dec 16 '12 at 23:16
    
Thank you for this answer. –  Pete Dec 20 '12 at 4:56

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.