Why Orthogonal Wire Routing Is a Topology Guarantee, Not Just a Visual Preference
TLDR
Constraining wire paths to 90° orthogonal (Manhattan) horizontal and vertical segments during drawing seems like a visual layout choice. In reality, it is a structural topology guarantee: it reduces port connection checks from complex $O(N \times M)$ line-segment distance calculations to exact axis-aligned bounding box (AABB) endpoint intersections. Enforcing orthogonality at draw time makes netlist generation, BOM extraction, and CAD file exports fast and reliable.| Routing Model | Connectivity Math Complexity | Endpoint Port Verification | Netlist Reliability |
|---|---|---|---|
| Free-Form Diagonal | $O(N \times M)$ Parametric segment math | Precision drift $\rightarrow$ False negatives | High ambiguity |
| Orthogonal (Manhattan) | $O(1)$ AABB Endpoint Intersection | Exact coordinate matching | 100% Deterministic |
Problem statement: the ambiguity of free-form diagonal wires
In diagramming applications, allowing free-form diagonal wires ($M\,x_1,y_1\,L\,x_2,y_2$) feels like the most flexible UX choice.
However, arbitrary diagonal paths push immense geometric complexity downstream into topology analysis.
Verifying whether a diagonal wire connects to a component pin requires testing whether a line segment intersects a pin's circular hit radius. Due to floating-point coordinate drift in draw loops, a wire that visually appears attached to a pin may miss it by 0.0001 units, causing netlist generators to report false disconnected nets.
Technical failure mode: parametric distance calculations
To resolve visual disconnection, developers often widen pin snap thresholds.
Widening thresholds creates a secondary defect: false positive connections, where wires passing near a component pin are incorrectly registered as connected pins in exported BOM netlists.
The fix & architecture: dominant axis locking at draw time
Enforce orthogonal constraints at segment creation by locking cursor movement to the dominant axis:
// Enforce orthogonal (Manhattan) routing on drag segment
function commitOrthogonalSegment(lastPt, cursorX, cursorY) {
const dx = Math.abs(cursorX - lastPt.x);
const dy = Math.abs(cursorY - lastPt.y);
// Lock segment to dominant axis return dx > dy ? { x: cursorX, y: lastPt.y } // Horizontal segment : { x: lastPt.x, y: cursorY }; // Vertical segment }
Exact AABB endpoint connectivity check
With orthogonal segments guaranteed, pin connectivity simplifies to two exact coordinate range checks:// O(1) Endpoint Connectivity Check
function isWireConnectedToPort(wireEndpoint, portBbox, epsilon = 2) {
return (
wireEndpoint.x >= portBbox.x - epsilon &&
wireEndpoint.x <= portBbox.x + portBbox.w + epsilon &&
wireEndpoint.y >= portBbox.y - epsilon &&
wireEndpoint.y <= portBbox.y + portBbox.h + epsilon
);
}
Degenerate zero-length segment removal
When moving attached components, recalculating orthogonal bend points can create zero-length segments ($x_1=x_2$ and $y_1=y_2$). Prune degenerate points after endpoint updates:function pruneDegenerateWirePoints(points) {
return points.filter((pt, i) => {
if (i === 0) return true;
const prev = points[i - 1];
return Math.hypot(pt.x - prev.x, pt.y - prev.y) > 0.001;
});
}
Rule of thumb: Enforce orthogonal Manhattan constraints at wire creation to simplify downstream topology analysis into $O(1)$ axis-aligned bounding box checks.