Engineering Journal
Schema Editor
Schema Editor

Classifying SVG Shapes by Geometry, Not by Class Names

2026-06-04

TLDR

Classifying SVG elements based on CSS classes (class="wire") or tag names (<circle>) locks your analyzer to specific authoring conventions and breaks on imported files. Evaluating intrinsic path geometry, specifically Linearity Ratio (endpoint span over path length) and Isoperimetric Quotient (circularity ratio $4\pi A / P^2$), classifies elements accurately across electrical, UML, and architectural domains without third-party class dependencies.
Shape CategoryGeometric ConditionLinearity RatioIsoperimetric Quotient ($4\pi A / P^2$)
Wire / ConductorOpen path$> 0.85$Near $0.0$
Junction / ConnectorClosed pathLow$> 0.65$ (Near $1.0$ for circles)
Component SymbolClosed / Complex pathVariable$< 0.65$ (e.g., $0.785$ for squares)

Problem statement: the fragility of metadata classifiers

When parsing vector diagrams from external sources (Inkscape, Illustrator, KiCad, or legacy exports), elements rarely carry standardized class names or custom data attributes.

An authoring tool might export a junction dot as an unclassed <path d="M...A...Z"> rather than a <circle class="junction">. A class-matching classifier defaults to treating these unclassed elements as generic components, excluding them from wire endpoint snapping and breaking topology netlist analysis.


Technical failure mode: silent topology analysis disruption

Relying on author metadata causes silent failures:

  1. Imported SVG files render visually on canvas, but topology engines return 'unknown' for unclassed shapes.
  2. Junctions fail to connect intersecting wires.
  3. Exported Bill of Materials (BOM) and netlist graphs omit valid connections without throwing runtime errors.

The fix & architecture: intrinsic geometric metrics

We replaced class-name lookups with a 2-metric geometric classification engine operating on normalized global coordinates:

1. Mathematical definitions

$$L = \frac{\text{hypot}(x_n - x_0, y_n - y_0)}{\text{totalPathLength}}$$

2. Geometry classifier implementation

function classifyByGeometry(pathPoints, isClosed) {
  if (pathPoints.length < 2) return 'unknown';

const len = computePathLength(pathPoints); if (len === 0) return 'unknown';

const endpointSpan = Math.hypot( pathPoints[pathPoints.length - 1].x - pathPoints[0].x, pathPoints[pathPoints.length - 1].y - pathPoints[0].y ); const linearity = endpointSpan / len;

// 1. Linearity Test: Straight or near-straight open paths are wires if (linearity > 0.85 && !isClosed) { return 'wire'; }

// 2. Circularity Test: Closed shapes with high circularity are junction dots if (isClosed) { const area = Math.abs(computeSignedArea(pathPoints)); const circularity = (4 Math.PI area) / (len * len); if (circularity > 0.65) { return 'connector'; // Highly circular junction dot } return 'component'; // Rectangular or complex symbol outline }

return 'component'; }

Rule of thumb: Always apply matrix transformations (DOMMatrix) to canonicalize path coordinates into world space before calculating geometry metrics. Use geometric classification as a fallback when CSS class metadata is missing.
Read this post in the full Engineering Journal →