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.

LineRectIntersection 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
56
57
58
59
60
// REQUIRES: LinePairRotation.pde
// REQUIRES: LineLineIntersection.pde

/**
 * Line-through-box intersection algorithm.
 *
 * INPUT x1,y1,x2,y2 constitute a line segment S1
 *       minx,miny,maxx,maxy constitute a world-aligned rectangular box
 *       colinearity is a boolean indicating whether or not lines that are
 *                   colinear with one of the box edges count as intersecting.
 *
 * Note that the follow assumptions are made: minx<maxx, miny<maxy
 *
 * RETURNS ArrayList<float[2/3]> representing all found intersections {x, y}
 *                               with an optional third element [2] that
 *                               indicates whether the intersections are on edges,
 *                               or (when the line segment is full contained
 *                               by the bounding box) somewhere inside the box.
 *
 * Note that we do not return null when no intersections are found, but
 * instead return an empty list. There's no point in checking the size
 * of the list every time this function is called.
 */
ArrayList<float[]> getLineRectIntersection(float x1, float y1, float x2, float y2, float minx, float miny, float maxx, float maxy, boolean colinearity) {
  ArrayList<float[]> intersections = new ArrayList<float[]>();

  // It's possible that the line segment is fully contained
  // by the bounding box. This is easily, and quickly, checked
  // for. Note that even though the conditional is four AND
  // clauses, boolean AND evaluation stops the moment any of them
  // is false, so we're doing at most four checks. 
  if (minx<min(x1,x2) && max(x1,x2)<maxx && miny<min(y1,y2) && max(y1,y2)<maxy) {
    // full containment makes the end points "intersections"
    intersections.add(new float[]{x1,y1,0});
    intersections.add(new float[]{x2,y2,0});
  }

  // If we get here, the line is not fully contained
  else {
    // form the four edges
    float[][] edges = {{minx, miny, maxx, miny},
                        {maxx, miny, maxx, maxy},
                        {minx, maxy, maxx, maxy},
                        {minx, miny, minx, maxy}};
    // perform line/line intersection detection for each edge
    for (float[] edge: edges) {
      float[] intersection = getLineLineIntersection(x1, y1, x2, y2, edge[0], edge[1], edge[2], edge[3], colinearity);
      if (intersection!=null) {
        intersections.add(intersection);
        // As we can't have more than two intersections,
        // stop iterating when we have found two of them.
        if(intersections.size()==2) { break; }
      }
    }
  }

  // At this point intersections is guaranteed
  // to contain all intersections. Return it.
  return intersections;
}

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.