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.
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.
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).
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.
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).
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.
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.