Commit Graph
7 Commits
Author SHA1 Message Date
rsp2k 55a869ef7d Add directions and lines with exact rational intersection
Ports Direction/IntDirection (equivalence classes of vectors, gcd-
normalized, exact angular compare) and Line. Line.side_of uses an exact
integer determinant; Line.intersection returns an IntPoint when the
crossing is integral and a RationalPoint otherwise, with the orthogonal
and 45-degree fast paths from the source preserved. Parallel lines yield
a point at infinity (z=0). BigIntDirection is folded into IntDirection
since unbounded int always fits.

Tests cover integral and rational intersections, parallel-line infinity,
exactness beyond double precision (verified via exact collinearity of the
result), and direction normalization/ordering.
2026-07-11 18:01:29 -06:00
rsp2k 33cb196bc8 Add exact planar points and vectors
Ports the point/vector foundation of geometry/planar: Side and Signum
(three-valued signs), Limits, FloatPoint (approximate), and the exact
IntPoint/IntVector plus projective RationalPoint/RationalVector.

Arithmetic model per type is documented in each module. The key
simplification over the Java source: Python's unbounded int makes the
exact orientation determinants and rational (x,y,z) coordinates trivial,
so side_of is kept exact (upstream uses a double for speed) and no
BigInteger or CRIT_INT overflow promotion is needed. Rational points use
the projective triple with z=0 denoting the point at infinity.

Tests cover collinearity, determinants beyond Java long range, rational
equality/reduction, and integer/rational promotion.
2026-07-11 18:01:21 -06:00
rsp2k 12b0a231f0 Implement Specctra SES session-file writer
Ports the write path of io/specctra/SesWriter.java to emit a valid
session from a parsed DsnBoard plus a RoutingResult. Each _write_*
function mirrors a write* method upstream:

- session scope with base_design, placement (resolution + components
  echoed from the DSN), an empty was_is, and routes
- routes carries resolution, a reduced parser scope, library_out with
  the via padstacks, and network_out
- network_out emits (net (wire (path layer width x1 y1 ...)) (via
  padstack x y)) for each routed net; integer coordinates via round-
  half-up to match Java Math.round

write_ses(board) with no result produces a valid no-op session,
proving the DSN-in / SES-out round trip. Only routes > network_out is
required by SesReader and kicad-cli; the rest is echoed for a
well-formed file.

18 tests: indent/quoting rules, no-op session structure, placement and
library_out echo, routed wire/via serialization, integer rounding, and
round-trips re-parsed through the project's own DSN tokenizer/sexp
(64 tests total across the suite, all green; ruff clean).
2026-07-11 16:34:19 -06:00
rsp2k 650c732a30 Add SES writer helpers: indent writer and routing-result model
Ports two FreeRouting building blocks for session output:

- indent.py: IndentWriter (2-space indented S-expression output) and
  Identifier (reserved-char/non-ASCII/leading-digit quoting), mirroring
  datastructures/IndentFileWriter and IdentifierType. The SES reserved
  set includes '-' and '_', so net and padstack names get quoted.
- model.py: RoutedWire/RoutedVia/RoutedNet/RoutingResult — the minimal
  in-memory routing structure the maze router will populate and the SES
  writer serializes. Coordinates are in DSN units.
2026-07-11 16:34:09 -06:00
rsp2k 3bf4f6bed2 Implement Specctra DSN parser with typed board model
Ports the read path of FreeRouting's io/specctra/parser package to a
Java-free Python implementation:

- tokenizer: S-expression lexer mirroring SpecctraFileDescription.flex
  (comments, quoted strings, the string_quote IGNORE_QUOTE directive,
  case-insensitive keywords, and hash-prefixed names)
- sexp: nested S-expression tree builder
- shapes: rect/circle/polygon/path plus area-with-holes scopes
- model: typed dataclasses for layers, padstacks, images, placements,
  nets, net classes, rules, keepouts
- reader: recursive-descent scope readers producing a DsnBoard, one
  _read_* function per FreeRouting read_scope method

46 pytest cases cover the tokenizer, tree, shapes, and end-to-end
parsing against hand-crafted fixtures modeled on FreeRouting's own
test DSN files. Parses 90 of 91 upstream fixtures (the one failure is
a binary OLE file, not text DSN).
2026-07-11 15:21:18 -06:00
rsp2k dc44abc7f7 Add architecture map of upstream FreeRouting source
Documents the packages relevant to the port (io/specctra DSN/SES,
board data model, geometry/planar primitives, autoroute core) with
verified upstream paths and Python-translation notes. Corrects the
seed plan's stale guesses: the Specctra code lives under io/specctra,
not designforms/specctra.
2026-07-11 15:21:09 -06:00
rsp2k 0270137b9f Scaffold freeroute: Python port of the FreeRouting engine
Pure-Python PCB autorouter replacing the freerouting.jar step in kicad-mcp.
Contract is Specctra DSN in, SES out — a drop-in for the JAR so the toolchain
needs no JVM. Includes pyproject (uv/ruff/pytest, src-layout) and a porting
plan seeded for study of the upstream FreeRouting Java source.
2026-07-11 14:51:42 -06:00