Point2D.Double p = new Point2D.Double(4.0,3.0),
q=new Point2D.Double(-3.0,4.0);
double angle = Math.atan(p.x/p.y)-Math.atan(q.x/q.y);
System.out.println("angle(radians)="+angle+", (degrees)="+
angle/Math.PI*180);
Your better off using atan2() and not atan() since the code above could cause dive by zero exceptions if either point has y=0.
Point2D.Double p = new Point2D.Double(4.0,3.0),
q=new Point2D.Double(-3.0,4.0);
double angle = Math.atan(p.y,p.x)-Math.atan(q.y,q.x);
System.out.println("angle(radians)="+angle+", (degrees)="+ angle/Math.PI*180);
Just out of curiosity, how on earth did you understand that question? I seem to remember that between any two points exists a LINE, but in order to have an angle you would have to have 3 points (one being the vertex). As I contemplate this question, my first thought is that the answer would depend on the placement of the "vertical line" and from which point on that vertical line you would be measuring the angle between the original two points. I am not challenging your answer, I am merely baffled that an answer could be formulated based on the VERY little information presented.
It's easy to understand if you think in terms of complex numbers.
Every (x,y) point on the complex plane can be equally well-represented by (r,t), where r = sqrt(x*x + y*y) and t = atan(y/x).
There's an implicit origin at (0,0) in the complex plane. That's the third point that the solution takes advantage of.
The solution simply calculates the angle for each point in the complex plane and subtracts the two to get the angular difference between them.
What I'm describing would be relative to the horizontal x-axis. There must be a transformation in there to give the results relative to the vertical axis, as the OP requested. - MOD
"measured from a vertical bar ?" I know how to measure an angle AOB where O is the origin, but I'm not sure what measuring from a bar might be.
The dot product of any two unit vectors is the cosine of the angle, so you can use that and avoid that pesky arctan.
theta = Math.acos(
(a.getX() * b.getX() + a.getY() * b.getY())
/ a.distance(0,0) / b.distance(0,0) );
Point2D.Double p = new Point2D.Double(4.0,3.0),
q=new Point2D.Double(-3.0,4.0);
double angle = Math.atan(p.y,p.x)-Math.atan(q.y,q.x);
System.out.println("angle(radians)="+angle+", (degrees)="+ angle/Math.PI*180);
Defend the hionour of atan2? Gaaah! you are making two[/d] calls to a math library! My code only needs to make one, to acos().
Firstly, of course, in the atan method the order of the operands is significant. In the dot product method, they are not. One gives "the angular distance from p to q", wheras the other gives "the angle between p and q".
Secondly, atan2 behaves ... oddly sometimes, I can never get straight whether the results are 0 to PI, or -PI/2 to PI/2. So if the angle is 60 degrees, you might get 60, -60, 120, -120, 300, -300 etc depending subtly on what the two points p and q contain, and all in floating point. You get the situation where the result flicks between two wildly different values when you move one of the points by a pixel, and the nature of the flick can change depending on which quarant the points are in. Been there, done that. The dot product method, by contrast, goes smoothly from 0 to PI.
Someone pass me a saucer of milk.
Hi pmurray,
Point well taken - one call to acos is better than atan2. That doesn't make it a superior function, that just says it's being used more efficiently by your algorithm. That's all I'm saying.
One more method call won't break a program's back. I'm not saying that I'm a fan of installing bubble sort and hoping for the best, but I'd wait until a profiler told me I had a problem in this case. Don't optimize prematurely. You don't always know where the bottleneck is. (Except maybe in this trivially obvious case.) ;)
I don't have a problem with the order of the arguments - I read the javadocs.
The "wild" nature you cite is due to the fact that atan2 is singular at +/-(pi/2), and it's periodic with period pi. It's not wild - a mathematician would say that's just the nature of the beast. But you're correct again - cosine is a smooth, non-singular function with an infinite number of continuous derivatives.
There's nothing wrong with anything you said. I'm just playing friendly devil's advocate. - MOD
> Point well taken - one call to acos is better than atan2. That doesn't make it a superior function, that just says it's being used more efficiently by your algorithm. That's all I'm saying.
Look, I'm just engaging in a little macho swaggering and petty point-scoring. Don't mind me. :-)
I would too, pmurray.
To be frank, I think what I said defending atan2 is pure ****, and I'm shocked that you didn't call me on it. ;)
I've decided that your point about using acos to calculate that angle is far superior. In my Complex class, I've changed the code to calculate the radius in the usual way and then get the angle using acos, per your suggestion. The lack of singularities in acos is impossible to pass up. Thanks - MOD
> The "wild" nature you cite is due to the fact that
> atan2 is singular at +/-(pi/2), and it's periodic with
> period pi. It's not wild - a mathematician would say
> that's just the nature of the beast
tan is singular at +/-((2n+1)pi/2) and has period pi.
Neither atan nor atan2 is periodic. As the range of tan is from -infinity to +infinity, the domain of atan is the same. The 2D domain of atan2 allows atan2 to range over -pi to + pi, giving a result over any of the four quadrants:
public class Atan {
public static void main(String[] args) {
System.out.println(Math.toDegrees(Math.atan2(-1, -1)));
System.out.println(Math.toDegrees(Math.atan2(1, 1)));
System.out.println(Math.toDegrees(Math.atan2(1, 0)));
System.out.println(Math.toDegrees(Math.atan2(-1, 0)));
System.out.println(Math.toDegrees(Math.atan(-1 / -1)));
System.out.println(Math.toDegrees(Math.atan(1 / 1)));
System.out.println(Math.toDegrees(Math.atan(Double.POSITIVE_INFINITY)));
System.out.println(Math.toDegrees(Math.atan(Double.NEGATIVE_INFINITY)));
}
}