1

I am calculating the intersection point of two lines with the following function:

// Functions of lines as per requested:
// f(y1) = starty1 + x * d1
// f(y2) = starty2 + x * d2
// x1 and y1 are the coordinates of the first point
// x2 and y2 are the coordinates of the second point
// d1 and d2 are the deltas of the corresponding lines
private static double[] intersect(double x1, double y1, double d1, double x2, double y2, double d2) {
    double starty1 = y1 - x1 * d1;
    double starty2 = y2 - x2 * d2;
    double rx = (starty2 - starty1) / (d1 - d2);
    double ry = starty1 + d1 * rx;

    tmpRes[0] = rx;
    tmpRes[1] = ry;

    return tmpRes;
}

// This is the same function, but takes 4 points to make two lines, 
// instead of two points and two deltas.
private static double[] tmpRes = new double[2];
private static double[] intersect(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) {
    double d1 = (y1 - y2) / (x1 - x2);
    double d2 = (y3 - y4) / (x3 - x4);
    double starty1 = y1 - x1 * d1;
    double starty2 = y3 - x3 * d2;
    double rx = (starty2 - starty1) / (d1 - d2);
    double ry = starty1 + d1 * rx;

    tmpRes[0] = rx;
    tmpRes[1] = ry;

    return tmpRes;
}

However as d1 or d2 get bigger (for vertical lines) the results are getting much less accurate. How can I prevent this from happening?

For my case I have two lines perpendicular to each other. If the lines are rotated 45 degrees, I get accurate results. If the lines are at 0 or 90 degrees, I get inaccurate results (one axis of the intersection is correct, the other is all over the place.

Edit

Using a cross product:

private static double[] crTmp = new double[3];
public static double[] cross(double a, double b, double c, double a2, double b2, double c2){
    double newA = b*c2 - c*b2;
    double newB = c*a2 - a*c2;
    double newC = a*b2 - b*a2;
    crTmp[0] = newA;
    crTmp[1] = newB;
    crTmp[2] = newC;
    return crTmp;
}


public static double[] linesIntersect(double x1, double y1, double d1, double x2, double y2, double d2)
{
    double dd1 = 1.0 / d1;
    double dd2 = 1.0 / d2;

    double a1, b1, a2, b2, c1, c2;
    if (Math.abs(d1) < Math.abs(dd1)) {
        a1 = d1;
        b1 = -1.0;
        c1 = y1 - x1 * d1;
    } else {
        a1 = 1.0;
        b1 = dd1;
        c1 = -x1 - y1 * dd1;
    }
    if (Math.abs(d2) < Math.abs(dd2)) {
        a2 = d2;
        b2 = -1.0;
        c2 = y2 - x2 * d2;
    } else {
        a2 = 1.0;
        b2 = dd2;
        c2 = -x2 - y2 * dd2;
    }

    double[] v1 = {a1, b1, c1};
    double[] v2 = {a2, b2, c2};
    double[] res = cross(v1[0], v1[1], v1[2], v2[0], v2[1], v2[2]);
    tmpRes[0] = res[0] / res[2];
    tmpRes[1] = res[1] / res[2];
    return tmpRes;
}
RobotRock
  • 4,211
  • 6
  • 46
  • 86
  • example please, as its not clear how result gets worse? Also if you meant decimal points accuracy then use BigDecimal. – SMA Nov 06 '15 at 09:23
  • Please explain what x1, y1 and d1 mean. – Andy Turner Nov 06 '15 at 09:24
  • Please explain what "delta of the corresponding lines" means. Please state the equations of the lines in terms of x, y and d. – Andy Turner Nov 06 '15 at 09:28
  • I've added an explanation of the variables in the comments of the code. Delta is the direction of the lines. Equations are added too. – RobotRock Nov 06 '15 at 09:32

1 Answers1

2

It is easiest if you use homogeneous notation:

  • Change your line representation from y = d*x + c to

    d*x - y + c = 0 = [d -1 c] . [x y 1]
    

    (where . means inner product)

  • Using this notation, you can write your lines as two vectors: [d1 -1 y1] and [d2 -1 y2]

  • Take the cross product of these two vectors, giving you a new vector:

    [d1 -1 y1] x [d2 -1 y2] = [a b c]
    

    (I'll leave you to look up how to calculate the cross product, but it's just simple multiplication)

The intersection of the two points is at (a/c, b/c). Provided the two lines are not parallel, c will be non-zero.

See: http://robotics.stanford.edu/~birch/projective/node4.html

One advantage of the a*x + b*y + c = 0 form of the line equation is that you can represent vertical lines naturally: you can't represent the line x = 1 by in the form y = m*x + c, because m would be infinity, whereas you can with 1*x + 0*y - 1 = 0.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • I've generated a new function according to your answer. I believe your last paragraph is the important where it's going wrong now. My new implementation still has the exact same fault, so something is still not well. – RobotRock Nov 06 '15 at 14:13