I have written generic Point classes, line/line intersection algorithms and Layer administration code more times than I can remember. I don't like menial programming, so this is effectively my code library. But you can use it too!
The language used is Processing, which is a mostly-Java-syntax language. I hardly ever use Java-specific ninja code, so rewriting any of these snippets to your favourite language is less than a minute's worth of work, typically.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | // REQUIRES: LinePairRotation.pde /** * Line-through-line intersection algorithm, using * relative rotation and intersection projection. * * INPUT x1,y1,x2,y2 constitute a line segment S1 * x3,y3,x4,y4 constitute a line segment S2 * colinearity is a boolean indicating whether * or not colinear lines count as * intersecting or not intersecting. * * RETURNS float[2] representing intersection {x, y}, * or "null" when there is no intersection. */ float[] getLineLineIntersection(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, boolean colinearity) { // perform a translation-rotation about (x3,y3) float angle = atan2(y4-y3, x4-x3), cosma = cos(-angle), sinma = sin(-angle); float[] tr = translateRotate(x1, y1, x2, y2, x3, y3, x4, y4, angle, cosma, sinma); // Can we short circuit based on the fact that line segment (1,2) // does not pass through the axis between x==0 and x==x4'? if (tr[0] < 0 && tr[2] < 0) { return null; } // x1<0 and x2<0: trivial reject if (tr[0] > tr[6] && tr[2] > tr[6]) { return null; } // x1>x3 and x2>x3: trivial reject // let's rule out colinear paths, too, if we were told // to do so through the "colinearity" function argument: if (!colinearity && tr[1]==0 && tr[3]==0) { return null; } // trivial reject, if desired // At this point we know the lines going through (x1/y1),(x2/y2) // and (x3,y3),(x4,y4) intersect. But we don't know whether the // line SEGMENTS (x1/y1),(x2/y2) and (x3,y3),(x4,y4) do. Let's find out. float dx = tr[2] - tr[0]; // x2' - x1'; float dy = tr[3] - tr[1]; // y2' - y1'; float factor = -tr[1] / dy; // -y1' / dy float ix = tr[0] + factor * dx; // x1' + factor*dx // The "factor" we just computed indicates where on the // line (x1/x2),(x2/y2) the intersection will be, as a value // between 0 and 1. If the value is <0 or >1, then the // intersection is wholly virtual, and we reject. if (factor<0 || factor>1) { return null; } // Alright, last check: what is the value for ix? // Since ix is the point on line (x3/y3),(x4/y4) // we can now finally say whether or not there's // an intersection between these two lines. if (ix<0 || ix>tr[6]) { return null; } // transform the intersection coordinate to real values return new float[]{x3+ix*cos(angle), y3+ix*sin(angle)}; } |
Written and maintained by Mike "Pomax" Kamermans. All code snippets on this site are "do whatever you want with it" licensed.