docs: function(obj) {
      if (!this.intersects(obj)) { return null; }
      if (obj.direction) {
        // obj is a line
        var A = obj.anchor.elements, D = obj.direction.elements,
            P = this.anchor.elements, N = this.normal.elements;
        var multiplier = (N[0]*(P[0]-A[0]) + N[1]*(P[1]-A[1]) + N[2]*(P[2]-A[2])) / (N[0]*D[0] + N[1]*D[1] + N[2]*D[2]);
        return Vector.create([A[0] + D[0]*multiplier, A[1] + D[1]*multiplier, A[2] + D[2]*multiplier]);
      } else if (obj.normal) {
        // obj is a plane
        var direction = this.normal.cross(obj.normal).toUnitVector();
        // To find an anchor point, we find one co-ordinate that has a value
        // of zero somewhere on the intersection, and remember which one we picked
        var N = this.normal.elements, A = this.anchor.elements,
            O = obj.normal.elements, B = obj.anchor.elements;
        var solver = Matrix.Zero(2,2), i = 0;
        while (solver.isSingular()) {
          i++;
          solver = Matrix.create([
            [ N[i%3], N[(i+1)%3] ],
            [ O[i%3], O[(i+1)%3]  ]
          ]);
        }
        // Then we solve the simultaneous equations in the remaining dimensions
        var inverse = solver.inverse().elements;
        var x = N[0]*A[0] + N[1]*A[1] + N[2]*A[2];
        var y = O[0]*B[0] + O[1]*B[1] + O[2]*B[2];
        var intersection = [
          inverse[0][0] * x + inverse[0][1] * y,
          inverse[1][0] * x + inverse[1][1] * y
        ];
        var anchor = [];
        for (var j = 1; j <= 3; j++) {
          // This formula picks the right element from intersection by
          // cycling depending on which element we set to zero above
          anchor.push((i == j) ? 0 : intersection[(j + (5 - i)%3)%3]);
        }
        return Line.create(anchor, direction);
      }
    }