tags:

views:

793

answers:

5

There is a very handy set of 2d geometry utilities here.

The angleBetweenLines has a problem, though. The result is always positive. I need to detect both positive and negative angles, so if one line is 15 degrees "above" or "below" the other line, the shape obviously looks different.

The configuration I have is that one line remains stationary, while the other line rotates, and I need to understand what direction it is rotating in, by comparing it with the stationary line.

EDIT: in response to swestrup's comment below, the situation is actually that I have a single line, and I record its starting position. The line then rotates from its starting position, and I need to calculate the angle from its starting position to current position. E.g if it has rotated clockwise, it is positive rotation; if counterclockwise, then negative. (Or vice versa.)

How to improve the algorithm so it returns the angle as both positive or negative depending on how the lines are positioned?

A: 

That function is working in RADS

There are 2pi RADS in a full circle (360 degrees)

Thus I believe the answear you are looking for is simply the returned value - 2pi

If you are asking to have that one function return both values at the same time, then you are asking to break the language, a function can only return a single value. You could pass it two pointers that it can use to set the value of so that the change can persist after the frunction ends and your program can continue to work. But not really a sensible way of solving this problem.

Edit

Just noticed that the function actually converts the Rads to Degrees as it returns the value. But the same principle will work.

thecoshman
+5  A: 
duffymo
This sounds great, but converting vector multiplication to code is a bit beyond me, I was hoping to be lazy and get it in code form :P i.e input: what I have, coordinates of endpoints of 2 lines; output: signed angle.
Jaanus
C'mon...vector multiplication is just multiplication. Can you code a recipe? Two vectors in, one vector out. What language do you want it in?
duffymo
Pseudocode or C is fine
Jaanus
Wow. Thanks for putting this together. I found my atan2 version more suitable for my needs, but perhaps this will be helpful for someone else reading this.
Jaanus
A: 

One 'quick and dirty' method you can use is to introduce a third reference line R. So, given two lines A and B, calculate the angles between A and R and then B and R, and subtract them.

This does about twice as much calculation as is actually necessary, but is easy to explain and debug.

swestrup
I understand atan2 basically does exactly that, with the x axis being the referance line.
Jaanus
+2  A: 
brainjam
All this vector stuff exploded my head. (Sorry, I forgot a lot of my math...) Now, I just calculate atan2 for both lines and compare these, works fine. Thanks.
Jaanus
Also implementation below.
Jaanus
+1  A: 

Here's the implementation of brainjam's suggestion. (It works with my constraints that the difference between the lines is guaranteed to be small enough that there's no need to normalize anything.)

CGFloat angleBetweenLinesInRad(CGPoint line1Start, CGPoint line1End, CGPoint line2Start, CGPoint line2End) {
    CGFloat a = line1End.x - line1Start.x;
    CGFloat b = line1End.y - line1Start.y;
    CGFloat c = line2End.x - line2Start.x;
    CGFloat d = line2End.y - line2Start.y;

    CGFloat atanA = atan2(a, b);
    CGFloat atanB = atan2(c, d);

    return atanA - atanB;
}

I like that it's concise. Would the vector version be more concise?

Jaanus
In my opinion, this should be the accepted answer.
Emil
I accepted brainjam's answer since I really asked for the algorithm, and in general I don't like accepting my own answers especially if it's a derivative of another answer, I like to give credit.
Jaanus