views:

356

answers:

4

Hi,

I have two Lines: L1 and L2. I want to calculate the angle between the two lines. L1 has points: {(x1, y1), (x2, y2)} and L2 has points: {(x3, y3), (x4, y4)}. How can I calculate the angle formed between these two lines, without having to calculate the slopes? The problem I am currently having is that sometimes I have horizontal lines (lines along the x-axis) and the following formula fails (divide by zero exception): arctan((m1 - m2) / (1 - (m1 * m2))) where m1 and m2 are the slopes of line 1 and line 2 respectively. Is there a formula/algorithm that can calculate the angles between the two lines without ever getting divide-by-zero exceptions? Any help would be highly appreciated.

This is my code snippet:

    // Calculates the angle formed between two lines
    public static double angleBetween2Lines(Line2D line1, Line2D line2)
    {
        double slope1 = line1.getY1() - line1.getY2() / line1.getX1() - line1.getX2();
        double slope2 = line2.getY1() - line2.getY2() / line2.getX1() - line2.getX2();
        double angle = Math.atan((slope1 - slope2) / (1 - (slope1 * slope2)));
        return angle;
    }

Thanks.

A: 

First, are you sure the brackets are in the right order? I think (could be wrong) it should be this:

   double slope1 = (line1.getY1() - line1.getY2()) / (line1.getX1() - line1.getX2());
   double slope2 = (line2.getY1() - line2.getY2()) / (line2.getX1() - line2.getX2());

Second, there are two things you could do for the div by zero: you could catch the exception and handle it

double angle;
try
{
    angle = Math.atan((slope1 - slope2) / (1 - (slope1 * slope2)));
catch (DivideByZeroException dbze)
{
    //Do something about it!
}

...or you could check that your divisors are never zero before you attempt the operation.

if ((1 - (slope1 * slope2))==0)
{
    return /*something meaningful to avoid the div by zero*/
}
else 
{
    double angle = Math.atan((slope1 - slope2) / (1 - (slope1 * slope2)));
    return angle;
 }
FrustratedWithFormsDesigner
Yeah sorry, forgot to add the brackets. But I mean, I don't really want to catch the exception because I dont need the slope in the first place. Even if I know if the line is horizontal, I didnt get the angle yet. I just need the angle between the two lines.
jNoob
@jNoob: if you don't want to catch the exception, then just check the divisors before any division operation.
FrustratedWithFormsDesigner
+6  A: 

Dot product is probably more useful in this case. Here you can find a geometry package for Java which provides some useful helpers. Below is their calculation for determining the angle between two 3-d points. Hopefully it will get you started:

public static double computeAngle (double[] p0, double[] p1, double[] p2)
{
  double[] v0 = Geometry.createVector (p0, p1);
  double[] v1 = Geometry.createVector (p0, p2);

  double dotProduct = Geometry.computeDotProduct (v0, v1);

  double length1 = Geometry.length (v0);
  double length2 = Geometry.length (v1);

  double denominator = length1 * length2;

  double product = denominator != 0.0 ? dotProduct / denominator : 0.0;

  double angle = Math.acos (product);

  return angle;
}

Good luck!

Joe
Yeah, dot product would be the way to go except doesn't creating a vector form of a line (which you need to do the dot product) basically involve getting the slope?
JGord
+3  A: 

The atan2 function eases the pain of dealing with atan.

It is declared as double atan2(double y, double x) and converts rectangular coordinates (x,y) to the angle theta from the polar coordinates (r,theta)

So I'd rewrite your code as

   public static double angleBetween2Lines(Line2D line1, Line2D line2)
    {
        double angle1 = Math.atan2(line1.getY1() - line1.getY2(),
                                   line1.getX1() - line1.getX2());
        double angle2 = Math.atan2(line2.getY1() - line2.getY2(),
                                   line2.getX1() - line2.getX2();
        return angle1-angle2;
    }
brainjam
That's impressive - upvoted.
Rekin
+3  A: 
dx1 = x2-x1;
dy1 = y2-y1;
dx2 = x4-x3;
dy2 = y4-y3;

d = dx1*dx2 + dy1*dy2;   // dot product of the 2 vectors
l2 = (dx1*dx1+dy1*dy1)*(dx2*dx2+dy2*dy2) // product of the squared lengths

angle = acos(d/sqrt(l2));

The dot product of 2 vectors is equal to the cosine of the angle time the length of both vectors. This computes the dot product, divides by the length of the vectors and uses the inverse cosine function to recover the angle.

phkahler