Engineering Journal
Schema Editor
Schema Editor

Postmortem: The Shape Classifier Broke Every Time We Added a New Domain

2026-06-04

TLDR

Our original shape classifier relied on hardcoded CSS class names (.wire, .junction, .component). As we expanded from electrical schematics to construction floorplans and software architecture diagrams, the classifier accumulated over 120 lines of domain-specific branching logic (if (domain === 'construction') ...). SVG imports continuously broke because imported files lacked class tags. Replacing class conditionals with a 4-phase geometric pipeline eliminated all domain branches.
System AspectLegacy Class ClassifierRefactored Geometric Pipeline
Domain ScalingRequired new if/else per domainZero domain-specific code
SVG Import CompatibilityFails on unclassed SVGs100% Compatible across all domains
Codebase Complexity~120 lines of nested branchingSingle unified math pipeline

Problem statement: the branching explosion across multi-domain support

Initially, our editor targeted electrical schematics: wires were .wire and junction dots were .junction.

When we added support for construction diagrams, walls (.wall) needed to behave like wires in connectivity analysis. When we added software architecture diagrams, dependency arrows (.dep-arrow) needed wire behavior while module containers (.module-box) needed component behavior.

The shape classifier evolved into a messy nested conditional:

// DEPRECATED: Domain-specific class branching (~120 lines deleted) if (domainMode === 'electrical') {   if (cls.includes('wire')) return 'wire'; } else if (domainMode === 'construction') {   if (cls.includes('wall')) return 'wire'; } else if (domainMode === 'software') {   if (cls.includes('dep-arrow')) return 'wire'; }

Every new domain required adding new class lists, and SVG imports from external tools failed completely.


Technical failure mode: the import desync incident

When a user imported an architectural floorplan SVG from Inkscape, the walls were exported as unclassed <path> elements.

Because cls.includes('wall') evaluated to false, the classifier categorized all wall paths as generic component nodes. Spatial wall-junction calculations failed silently, generating broken structural reports.


The fix & architecture: the 4-phase geometric pipeline

We deleted 120 lines of domain conditional logic and replaced them with a 4-phase geometric pipeline:

  1. Path Extraction & Parsing: Parse path d attributes into point arrays.
  2. Coordinate Canonicalization: Apply matrix transforms (DOMMatrix) to convert points to global world space.
  3. Metric Calculation: Compute Linearity Ratio ($L$) and Isoperimetric Quotient ($Q$).
  4. Classification Pass: Evaluate universal thresholds ($L > 0.85 \rightarrow \text{wire}$; $Q > 0.65 \rightarrow \text{connector}$).
// REFACTORED: Unified 4-phase geometry classifier
function classifyElement(el) {
  // Respect explicit metadata override if present
  const meta = el.getAttribute('data-geo-class');
  if (meta) return meta;

// Universal geometric fallback const points = extractGlobalWorldPoints(el); const isClosed = isPathClosed(el); return classifyByGeometry(points, isClosed); }

A wall in a construction diagram and a wire in an electrical schematic both exhibit high linearity ($L > 0.85$). The geometric classifier identifies both correctly without knowing or caring which domain is active.

Rule of thumb: Eliminate domain-specific class branching by deriving classifications from intrinsic spatial properties rather than author-assigned metadata.
Read this post in the full Engineering Journal →