function thetaStar(grid: Grid, start: Cell, goal: Cell) {const open = new MinHeap<Cell>([start]), distance = new Map([[start, 0]]), parent = new Map([[start, start]]);
while (open.size > 0) {const current = open.pop(); // lowest distance + straight line to the goal
if (current === goal) return rebuild(parent, current);
for (const neighbor of neighbors(grid, current)) {const grandparent = parent.get(current)!;
const via = lineOfSight(grid, grandparent, neighbor) ? grandparent : current;
const candidate = distance.get(via)! + euclid(via, neighbor);
if (candidate >= (distance.get(neighbor) ?? Infinity)) continue;
distance.set(neighbor, candidate); parent.set(neighbor, via);
open.push(neighbor, candidate + euclid(neighbor, goal));
}
}
}
Start at (12, 1), goal at (5, 42). Like A*, but a cell's parent may be any earlier cell it can see in a straight line.
Understanding Theta*
The idea
A* on a grid returns paths made of grid moves, so a diagonal crossing of open ground becomes a staircase up to 41% longer than the straight line. Theta* fixes that in one place: when it relaxes a neighbour, it first checks whether the neighbour can see the current cell's parent in a straight line, and if so links it straight to that parent instead.
Paths become sequences of a few waypoints joined by straight segments, with Euclidean lengths, while the search itself is still A* over the same cells. It is not guaranteed optimal among all any-angle paths, but it is within a percent or two of the true shortest in practice.
The four stages
Complexity
Versus its siblings
Pseudocode
THETA*(start, goal)
open ← {start}; dist[start] ← 0; parent[start] ← startwhile open not empty
current ← the open cell with the lowest dist + euclid(current, goal); if it is the goal: rebuild the path
for each neighbour of current
via ← parent[current] if it can see neighbour in a straight line, else current
if dist[via] + euclid(via, neighbour) < dist[neighbour]: update dist, parent[neighbour] ← via, add neighbour to open
When to use
Pitfalls
History
Alex Nash, Kenny Daniel, Sven Koenig and Ariel Felner introduced Theta* in 2007 as the first any-angle search that runs at A* speed; Lazy Theta* followed in 2010. Anya, from 2013, finally gave an optimal any-angle algorithm, at the cost of a more complex search space.