I don't want to keep writing the same code over and over.

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.

LineLineIntersection snippet

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)};
}

Back to the main page

Download all


Written and maintained by Mike "Pomax" Kamermans. All code snippets on this site are "do whatever you want with it" licensed.