Find Closest Point on a Line Segment in Three.js

In 3D computer graphics, finding the nearest point on a line segment to an arbitrary point in space is a common task used for collision detection, pathfinding, and user interactions. The Three.js library simplifies this mathematical challenge through its utility class, Line3. This article explains how to utilize the Line3 class, specifically its closestPointToPoint method, to efficiently calculate this closest point on a line segment with minimal code.

The Line3 class represents a 3D line segment defined by a start point and an end point, both of which are Vector3 instances. Rather than manually calculating vector projections and dot products, developers can leverage Line3’s built-in methods to handle the geometry.

How the closestPointToPoint Method Works

The primary method used for this calculation is closestPointToPoint(point, clampToLine, target). It takes three arguments:

  1. point (Vector3): The external point in 3D space from which you want to find the closest point on the line segment.
  2. clampToLine (Boolean):
    • If set to true, the returned point is guaranteed to lie strictly on the segment between the start and end points. If the closest mathematical projection falls outside the segment, the method returns the nearest endpoint (start or end).
    • If set to false, the method treats the segment as an infinite line extending in both directions and returns the projection of the point along that infinite line.
  3. target (Vector3): The vector where the resulting coordinates will be written. Passing a target vector avoids creating new object instances in memory, which is crucial for maintaining high performance in real-time rendering loops.

Code Example

Here is a practical example demonstrating how to set up a line segment and find the closest point to a target coordinate:

import * as THREE from 'three';

// 1. Define the start and end points of the line segment
const start = new THREE.Vector3(0, 0, 0);
const end = new THREE.Vector3(10, 0, 0);

// 2. Instantiate the Line3 object
const lineSegment = new THREE.Line3(start, end);

// 3. Define the external point in space
const externalPoint = new THREE.Vector3(5, 5, 0);

// 4. Create a target vector to store the result
const result = new THREE.Vector3();

// 5. Calculate the closest point, clamping it to the segment
lineSegment.closestPointToPoint(externalPoint, true, result);

console.log(result); // Output: Vector3 { x: 5, y: 0, z: 0 }

In this example, the external point is directly above the midpoint of the line segment. The closestPointToPoint method drops a perpendicular line to the segment, accurately identifying (5, 0, 0) as the closest point.

Underlying Mathematics

Under the hood, Line3 projects the vector pointing from the start of the line to the external point onto the line segment’s direction vector. By calculating the dot product, Three.js determines a scalar projection value, \(t\). - When clampToLine is true, this \(t\) value is clamped between 0 (the start point) and 1 (the end point). - The final coordinates are calculated by interpolating along the line segment using this clamped \(t\) value.

By encapsulating this linear algebra, the Line3 class provides an optimized, readable, and error-free way to perform spatial queries in Three.js applications.