Connector Symbols Misclassified as Components After SVG Import
TLDR
A small junction dot imported from an external SVG has no class="junction" attribute. The class-based classifier returns 'component'. Topology analysis misses the junction and produces incorrect connectivity. Computing circularity = 4πA/P² from the path points catches it correctly: circles score near 1.0, well above the 0.65 connector threshold.
Symptom
A circuit diagram is imported from an SVG file produced by another tool. Three-way wire junctions (small filled circles where wires cross) appear visually correct on the canvas. Topology analysis reports the wires as disconnected at the junction points. The BOM shows separate nets that should be connected.
The classifier returns 'component' for the junction circles. They are excluded from the wire endpoint snapping pass and the port discovery pass. Wires on either side of the junction have no shared endpoint.
Why It Happens
The class-name classifier checks el.classList.contains('junction') or el.tagName === 'circle'. Imported circles may use <path> elements instead of <circle> (Inkscape converts all shapes to paths on export). The path has no class attribute. The classifier defaults to 'component'.
// wrong: fails for path-based circles with no class
function classify(el) {
if (el.classList.contains('junction')) return 'connector';
if (el.tagName === 'circle') return 'connector';
return 'component'; // catches everything else, including imported circles
}
The Fix
Compute circularity from the element's path points after parsing and flattening the path data:
function classifyByGeometry(points, isClosed) {
const len = pathLength(points);
if (len === 0) return 'unknown';
// Linearity check first (cheap): high linearity = wire const span = Math.hypot( points.at(-1).x - points[0].x, points.at(-1).y - points[0].y ); if (span / len > 0.85 && !isClosed) return 'wire';
// Circularity for closed shapes: near 1.0 = circle = connector if (isClosed) { const area = Math.abs(signedArea(points)); const circularity = (4 Math.PI area) / (len * len); if (circularity > 0.65) return 'connector'; }
return 'component'; }
A path-based circle (32 approximation segments) scores circularity ~0.98. A square scores ~0.785. A resistor symbol (rectangular with leads) scores ~0.15. The threshold of 0.65 cleanly separates connector dots from component symbols.
Apply this after the path's d attribute is parsed into points and the element's transform attribute is applied to get global coordinates.
How to Prevent It
Add a test case that imports an SVG containing a <path> element that approximates a circle (generated by Inkscape or equivalent) and asserts that it classifies as 'connector'. This catches the regression if the class-name path is re-added later.
The Generalizable Lesson
When classifying shapes from external input, trust geometry over metadata. Metadata (class names, IDs) is author convention. Geometry is structural truth. A circle is a circle regardless of what tag or class the author chose.