boutell@freezer.it.udel.edu (Tom Boutell) (10/01/90)
Having failed to find this one in the frequently asked questions cate- gory, I'm going to go ahead and post it. I need a decent algorithm for determining the intersections of lines. No, I haven't forgotten all my algebra (-:, but the standard formulas have something lacking when one *or* both lines are nearly vertical; the degree of error tends to be great. Is there an accepted solution to the problem for integer arithmetic, reliable down to one- pixel accuracy? -- What do you want from the fish of the fish that you fished when you fished for the fish that you fished? How many numchuks could Chuck chuck if Chuck could chuck numchuks? boutell@freezer.it.udel.edu? Or 27.598234821? Or not?
markv@gauss.Princeton.EDU (Mark VandeWettering) (10/01/90)
In article <31960@nigel.ee.udel.edu> boutell@freezer.it.udel.edu (Tom Boutell) writes: >Having failed to find this one in the frequently asked questions cate- >gory, I'm going to go ahead and post it. I need a decent algorithm >for determining the intersections of lines. No, I haven't forgotten >all my algebra (-:, but the standard formulas have something lacking >when one *or* both lines are nearly vertical; the degree of error >tends to be great. Is there an accepted solution to the problem for >integer arithmetic, reliable down to one- pixel accuracy? You betray the fact that you are trying to represent your line as the typical y = mx + b type for form. Much easier to deal with is a vector equation P1 + t (P2 - P1), where P1 = {x1, y1}, and P2 = {x2, y2}, and t ranges between zero and one. Given your segments L1 = P1 + s (P2 - P1) and L2 = P3 + t (P4 - P2), you need to find the s and t values where they are equal. Well, this means that x1 + s (x2 - x1) = x3 + t (x4 - x3) y1 + s (y2 - y1) = y3 + t (y4 - y3) which are two equations in two unknowns, which you can easily solve by substituting one into the other. The case where the lines are parallel is exactly when (x2 - x1) == (x4 - x3) and (y2 - y1) == (y4 - y3). Otherwise they cross. Conversion to integer math is left as an exercise, as I hate using machines without blazingly fast floating point :-) Mark
bruceh@sgi.com (Bruce R. Holloway) (10/02/90)
In article <31960@nigel.ee.udel.edu> boutell@freezer.it.udel.edu (Tom Boutell) writes: >Having failed to find this one in the frequently asked questions cate- >gory, I'm going to go ahead and post it. I need a decent algorithm >for determining the intersections of lines. No, I haven't forgotten >all my algebra (-:, but the standard formulas have something lacking >when one *or* both lines are nearly vertical; the degree of error >tends to be great. Is there an accepted solution to the problem for >integer arithmetic, reliable down to one- pixel accuracy? The equation of a line in 2-space may be expressed without any division as | x y 1 | | x1 y1 1 | = 0, | x2 y2 1 | where (x1,y1) and (x2,y2) are points on the line. This may also be written | x1 y1 | x(y1-y2) - y(x1-x2) + | x2 y2 | = 0. For a second line through (x3,y3) and (x4,y4), | x3 y3 | x(y3-y4) - y(x3-x4) + | x4 y4 | = 0. Solving simultaneously, | x1 y1 | | x3 y3 | | x2 y2 |(x3-x4) - (x1-x2)| x4 y4 | x = -----------------------------------, and | (x1-x2) (y1-y2) | | (x3-x4) (y3-y4) | | x1 y1 | | x3 y3 | | x2 y2 |(y3-y4) - (y1-y2)| x4 y4 | y = -----------------------------------, | (x1-x2) (y1-y2) | | (x3-x4) (y3-y4) | which can be evaluated with integer arithmetic of sufficient precision. Regards, bruceh
turk@Apple.COM (Ken "Turk" Turkowski) (10/11/90)
In article <31960@nigel.ee.udel.edu> boutell@freezer.it.udel.edu (Tom Boutell) writes: >Having failed to find this one in the frequently asked questions cate- >gory, I'm going to go ahead and post it. I need a decent algorithm >for determining the intersections of lines. No, I haven't forgotten >all my algebra (-:, but the standard formulas have something lacking >when one *or* both lines are nearly vertical; the degree of error >tends to be great. Is there an accepted solution to the problem for >integer arithmetic, reliable down to one- pixel accuracy? Good that you remember your algebra. Remember Gaussian elimination with partial or full pivoting from your elementary numerical methods course? You can cast the line intersection problem as a matrix equation: [x y] | A B | = [e f] | C D | With floating-point arithmetic, you can get away with partial pivoting (pivoting aroung the largest magnitude element in a row), but for fixed-point arithmetic, you need to do full pivoting (pivoting around the largest element in the matrix). -- Ken Turkowski @ Apple Computer, Inc., Cupertino, CA Internet: turk@apple.com Applelink: TURK UUCP: sun!apple!turk
chris@ncmicro.lonestar.org (Chris Arps) (10/12/90)
/* Intersection of two 2d lines - Chris Arps, NC Microproducts Inc. */ /* $Func - interltl() intersect two lines */ /* $Input - x1,y1 start point of line #1 */ /* x2,y2 end point of line #1 */ /* x3,y3 start point of line #2 */ /* x4,y4 end point of line #2 */ /* $Output - x5,y5 intersection point of two lines */ /* $Returns - < 0 no intersection due to parallel,too small, etc. */ /* x5,y5 are NOT computed */ /* 0 x5,y5 computed , line segments do not touch */ /* 1 x5,y5 computed , line segments touch */ #define ABSZERO 1.0E-10 /* tolerance for zero, works on PC/Sun */ int interltl(x1,y1,x2,y2,x3,y3,x4,y4,x5,y5) double x1,y1,x2,y2,x3,y3,x4,y4; double *x5,*y5; { extern double fabs(),sqrt(); double a1,b1,c1,a2,b2,c2; double x,y,t0,t1; a1 = y1 - y2; b1 = x2 - x1; c1 = x1*y2 - x2*y1; a2 = y3 - y4; b2 = x4 - x3; c2 = x3*y4 - x4*y3; y = a1*b2 - a2*b1; x = a1 - a2; if ( fabs(y) < ABSZERO) { /* parallel */ x = x1*y2 + x3*y1 + x2*y3 - x3*y2 - x1*y3 - x2*y1; if ( fabs(x) < ABSZERO ) return -2; /* collinear */ return -1; } y = (a2*c1 - a1*c2) / y; if ( fabs(x) < ABSZERO) return -3; /* both horizontal */ x = (b2*y - b1*y + c2 - c1) / x; if ( fabs(x2-x1) < ABSZERO ) { if (fabs(y2-y1) < ABSZERO ) return -4; /* line too small */ else t0 = (y - y1) / (y2 - y1); } else t0 = (x - x1) / (x2 - x1); if ( fabs(x4-x3) < ABSZERO ) { if (fabs(y4-y3) < ABSZERO ) return -4; /* line too small */ else t1 = (y - y3) / (y4 - y3); } else t1 = (x - x3) / (x4 - x3); *x5 = x; *y5 = y; if ( t0 < ABSZERO || t0 > (1.0 - ABSZERO) || t1 < ABSZERO || t1 > (1.0 - ABSZERO) ) return 0; return 1; }