raw Math
RAW Math Linear Algebra Computational Geometry

Normal Vectors of a Line Segment

Robert Eisele

For two distinct points \(\mathbf A=(A_x,A_y)\) and \(\mathbf B=(B_x,B_y)\), the directed line segment has direction

\[ \mathbf v=\mathbf B-\mathbf A=(B_x-A_x,\,B_y-A_y). \]

Rotating \(\mathbf v\) counterclockwise by \(90^\circ\) applies the 2D perp operator:

\[ \mathbf n_\text{left}=\mathbf v^\perp=(-v_y,v_x). \]

The opposite vector is the right-hand normal:

\[ \mathbf n_\text{right}=-\mathbf n_\text{left}=(v_y,-v_x). \]

Both vectors have the same length as the segment direction. Divide them by \(\lVert\mathbf v\rVert\) when unit normals are required.

JavaScript Implementation

function lineSegmentNormals(A, B, unitLength = false) {
  const dx = B.x - A.x;
  const dy = B.y - A.y;
  const length = Math.hypot(dx, dy);

  if (length === 0) return null;

  const scale = unitLength ? 1 / length : 1;
  return [
    {x: -dy * scale, y: dx * scale},
    {x: dy * scale, y: -dx * scale}
  ];
}

The first result points to the left of the directed segment \(A\to B\); the second points to the right. Reversing the endpoints swaps these two directions. Equal endpoints return null because a zero-length segment has no direction and therefore no defined normal.

const A = {x: 1, y: 2};
const B = {x: 4, y: 6};

lineSegmentNormals(A, B);
// [{x: -4, y: 3}, {x: 4, y: -3}]

lineSegmentNormals(A, B, true);
// [{x: -0.8, y: 0.6}, {x: 0.8, y: -0.6}]