Schema Editor
The Magic of Manhattan: Implementing Intelligent Orthogonal Routing in Vanilla JS
TLDR
In engineering schematics, wire routing must follow clean 90° orthogonal paths ("Manhattan routing") to prevent messy, unreadable "spaghetti" diagrams. The GINEXYS Schema Editor implements a modified A* pathfinding algorithm on a dynamic grid with heavy turn penalization (favoring long straight segments over staircase steps) and optional 45° chamfered corners. Real-time net tracing uses a spatial KD-tree to traverse connectivity graphs at 60fps in pure Vanilla JS SVG.| Feature Component | Routing Mechanism | Engineering Benefit |
|---|---|---|
| A* Orthogonal Router | Turn penalization cost function | Eliminates staircase wire bends |
| 45° Corner Chamfering | SVG path corner smoothing | Reduces visual clutter & reflects PCB practices |
| Real-time Net Tracing | KD-Tree spatial index traversal | Instant 60fps signal path highlighting |
Problem statement: the spaghetti wire problem in visual CAD
In open-source diagramming tools, wires are often rendered as simple straight diagonal lines or basic Bezier curves.
In complex electrical, architectural, or software schematics, diagonal wires crossing over components create unreadable "spaghetti" layouts. Wires must route orthogonally around component bounding boxes while maintaining clean 90° bends.
Technical failure mode: staircase bends in standard A* pathfinding
Standard A* pathfinding evaluates path cost based purely on Euclidean or Manhattan distance.
When routing between two pins that are offset both horizontally and vertically, standard A* treats a series of small 1-unit staircase steps (right-down-right-down) as identical in cost to a clean two-segment elbow (right-then-down). This results in jagged, unreadable wire paths.
The fix & architecture: turn penalization & spatial net tracing
1. Turn penalization in pathfinding cost
We modified the A* pathfinding heuristic to add a heavy cost penalty whenever a step changes direction by 90°:// Heuristic Cost: Distance + Heavy Turn Penalty
function calculateStepCost(currentDirection, nextDirection, baseDistance) {
const isTurn = currentDirection !== nextDirection;
const turnPenalty = isTurn ? 50 : 0; // Heavy penalty forces long straight segments
return baseDistance + turnPenalty;
}
2. Direct SVG DOM manipulation for 60fps dragging
Rather than using virtual DOM frameworks (React/Vue) that introduce rendering latency during component dragging, wire paths mutate SVGd attributes directly:
// Direct DOM mutation during component drag
function updateWirePath(wireSvgPathEl, pointArray) {
const pathData = generateManhattanPathD(pointArray); // Generates 'M x y L x y...'
wireSvgPathEl.setAttribute('d', pathData);
}
3. Spatial KD-tree net tracing
When a user clicks a wire in Trace Mode, the engine executes a recursive graph traversal using a spatial KD-tree index, highlighting the entire electrical net (source, resistors, IC pins) instantly across thousands of elements.Rule of thumb: Add heavy turn penalties to A* pathfinding heuristics when building schematic wire routers to force clean orthogonal paths over staircase steps.
Read this post in the full Engineering Journal →