Skip to content

Spec: Dual-Unit Grid System (Metric/Imperial)

Overview

Refactor the coordinate and grid system to support both metric (mm) and imperial (mil/inch) units with proper grid presets for schematic capture and future PCB layout. Introduce type-safe coordinate handling, a unified snap engine, and standard EDA grid series.

Motivation

DigitalWorks is evolving from a digital logic simulator into a full schematic editor and eventually a PCB design tool. Professional EDA tools (KiCad, Altium, DipTrace, Eagle) all support dual-unit systems because:

  • Schematic symbols use mil-based grids (50 mil pin pitch is universal)
  • PCB components mix imperial (through-hole on 100 mil) and metric (fine-pitch SMD on 0.5mm/0.4mm)
  • Users expect to toggle between mm and mil display freely
  • File interchange requires unambiguous unit metadata

The current system stores coordinates in mils with PixelsPerMil = 1.0, which is correct for schematics but needs formalization for PCB support.

Current State

  • Internal unit: mils (implicitly, via MeasurementSystem.cs with PixelsPerMil = 1.0)
  • Grid: Single GridSizeInUnits (default 50 mil) in GridSettings
  • Snap: Duplicated in GridSettings.SnapToGrid() and CircuitEditorAdapter.Snap()
  • Persistence: Raw doubles in .dwcircuit JSON, no unit metadata
  • Shape definitions: Coordinates in component-local mils (10, 20, 40, 60 etc.)
  • Display: No user-visible unit indicator or switching

Requirements

Functional Requirements

FR-1: Unit System

  • Support three display units: Millimeter (mm), Mil (thou), Inch
  • Internal storage remains mil-based (1 mil = 0.0254 mm) for backward compatibility
  • All coordinate display, input fields, and rulers show values in the selected display unit
  • Unit switching is instant (no data conversion — only display changes)

FR-2: Grid Presets

  • Schematic grid presets (mil-based, standard EDA series):
    • 50, 25, 10, 5 mil
  • PCB Imperial grid presets:
    • 100, 50, 25, 12.5, 6.25, 3.125, 1 mil
  • PCB Metric grid presets:
    • 2.54, 1.27, 0.635, 0.5, 0.25, 0.1, 0.05 mm
  • Custom grid size entry (in current display unit)
  • Grid presets organized by context (Schematic / PCB Imperial / PCB Metric)

FR-3: Snap Engine

  • Single unified snap implementation (eliminate duplication)
  • Snap-to-grid (configurable on/off, Ctrl to temporarily toggle)
  • Snap-to-pin (when dragging wire endpoints near component pins)
  • Snap-to-object (alignment guides to nearby component edges)
  • All snap operations respect the active grid size

FR-4: Coordinate Display

  • Status bar shows cursor position in current display unit
  • Component property panels show position/size in current display unit
  • Grid size selector shows values in current display unit
  • Ruler/measurement overlays in current display unit

FR-5: File Format

  • .dwcircuit JSON includes "units": "mil" metadata field
  • Files without unit metadata assumed to be mils (backward compatible)
  • Future: support saving in mm-based files for PCB context

Non-Functional Requirements

  • NF-1: Unit conversion must be lossless at display precision (3 decimal places for mm, 1 for mil)
  • NF-2: Snap operations must be O(1) per point (no scanning)
  • NF-3: Grid rendering must not allocate per frame
  • NF-4: Backward compatible — existing .dwcircuit files load without changes

Design

Internal Coordinate Unit

Keep mils as the internal unit. This matches the existing codebase, all shape definitions, and is the natural unit for schematic capture (50-mil symbol grid, 100-mil pin pitch).

For future PCB mode, mils remain appropriate — KiCad uses nanometers internally but mils are sufficient for schematic-level precision and simpler to reason about.

Grid Preset Series

The DipTrace-style mm values are simply the imperial series converted:

Imperial (mil)    Metric (mm)
─────────────    ───────────
  1              0.0254
  3.125          0.0794
  6.25           0.159
  12.5           0.318
  25             0.635
  31.25          0.794
  50             1.27
  100            2.54
  150            3.81
  200            5.08
  300            7.62

Additional metric-native grids for fine-pitch SMD:

  • 0.5 mm (19.685 mil) — QFP/QFN pitch
  • 0.4 mm (15.748 mil) — fine BGA pitch
  • 0.25 mm (9.843 mil) — ultra-fine pitch
  • 0.1 mm (3.937 mil) — precision routing

Architecture

┌─────────────────────────────────────┐
│           Display Layer             │
│  (mm / mil / inch formatting)       │
├─────────────────────────────────────┤
│         Snap Engine                 │
│  (grid snap, pin snap, object snap) │
├─────────────────────────────────────┤
│       GridSettings                  │
│  (grid size, presets, visibility)   │
├─────────────────────────────────────┤
│      MeasurementSystem              │
│  (unit conversions, internal→display│
│   display→internal, formatting)     │
├─────────────────────────────────────┤
│      Internal Coordinates           │
│  (all values stored in mils)        │
└─────────────────────────────────────┘

Key Classes

  • MeasurementSystem — static unit conversion + formatting (exists, to be extended)
  • GridPresets — defines standard grid series for each context
  • SnapEngine — unified snap logic (replaces dual implementations)
  • GridSettings — grid configuration (exists, to be extended with presets)
  • CoordinateFormatter — formats coordinates for display in current unit

Implementation Tasks

  1. Extend MeasurementSystem with grid preset series and formatting helpers
  2. Add GridPresets class with Schematic/PCB-Imperial/PCB-Metric series
  3. Create SnapEngine replacing dual snap implementations
  4. Update GridSettings to use preset system and expose unit-aware grid size
  5. Add unit metadata to .dwcircuit file format
  6. Update status bar cursor display to show units
  7. Update Preferences grid size selector with preset dropdown
  8. Add unit toggle (mm/mil) to status bar or toolbar

Migration

  • Existing files: no unit header → assume mils (current behavior preserved)
  • Existing grid sizes: remain valid (50 mil default unchanged)
  • Shape definitions: no change needed (already in mils)
  • Pin positions: no change needed (already in mils)