Skip to content

Preserve OSM one-way direction during generation - #105

Open
FrogAi wants to merge 1 commit into
pfeiferj:mainfrom
FrogAi:codex/preserve-one-way-generation
Open

Preserve OSM one-way direction during generation#105
FrogAi wants to merge 1 commit into
pfeiferj:mainfrom
FrogAi:codex/preserve-one-way-generation

Conversation

@FrogAi

@FrogAi FrogAi commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Developer summary

Offline generation currently treats only the literal oneway=yes as one-way. That loses fixed reverse direction (-1), legacy 1, and the standard roundabout/motorway implications. Because the stored format represents direction as a Boolean plus node order, simply marking -1 true would invert the permitted direction and its directional speed metadata.

This canonicalizes supported fixed directions during generation: reverse ways are stored in the permitted order with both forward/backward speed pairs swapped. It also resolves the repeated-endpoint ambiguity for closed one-way ways. No schema change is needed.

Verification

  • An external matrix covers yes, 1, -1, no, 0, missing tags, explicit overrides, roundabout/motorway inference, non-inferred lookalikes, both directional speed pairs, and open/closed runtime classification.
  • The focused matrix passes 100 consecutive runs; repository-wide test, race, vet, and build gates pass on Linux/Go 1.25.1.

Compatibility

IDs, boxes, non-directional metadata, schemas, settings, and APIs are unchanged. Existing tiles are not rewritten; corrected behavior appears after regeneration. Dynamic/conditional/mode-specific direction remains outside this fixed-direction representation.


Engineering record and audit trail

Root cause

Current generation sets OneWay only when the raw OSM value is exactly yes, then copies source node order and directional speed fields unchanged. Runtime treats stored-forward as the permitted direction whenever the Boolean is true.

That representation cannot store oneway=-1 directly: traffic is permitted opposite the source node order. Canonicalizing it requires reversing the stored nodes and moving every direction-dependent value with the real travel direction. Otherwise runtime would reject the legal direction and select the wrong forward/backward speed fields.

Closed OSM ways repeat their first node at the end. The existing endpoint check therefore classifies a closed way at that shared junction as backward. Once a closed roundabout is correctly marked one-way, ordinary direction checks would reject its stored-forward direction.

Implementation

  • yes and legacy 1 remain in source order and are stored one-way.
  • -1 is stored one-way with reversed nodes, swapped numeric forward/backward speeds, and swapped forward/backward conditional strings.
  • A missing or empty primary oneway value implies forward direction only for junction=roundabout and highway=motorway.
  • Explicit values such as no, 0, reversible, and alternating suppress those implications.
  • IsForwardFrom treats a closed one-way match at its exact repeated endpoint as stored-forward.

Generator behavior

OSM input Current main This branch
oneway=yes Forward one-way Unchanged
Legacy oneway=1 Two-way Forward one-way
oneway=-1 Two-way; source order One-way; reversed nodes; both directional speed pairs swapped
Ordinary missing/empty oneway Two-way Unchanged
Missing/empty on roundabout or motorway Two-way Forward one-way
Explicit no or 0 on implied features Two-way Unchanged; explicit value wins
Missing on motorway link or junction=circular Two-way Unchanged; no inference
Dynamic or another explicit value Two-way Unchanged; outside the fixed-direction schema

Name, ref, hazard, lanes, ID, highway class, bounding box, general speed, advisory speed, and general conditional speed remain unchanged.

Runtime direction classification

Geometry at junction Current main This branch
Open one-way at first node Forward Unchanged
Open one-way at last node Reverse Unchanged
Closed one-way at repeated first/last node Reverse Forward
Closed two-way at repeated first/last node Reverse classification, still legal Unchanged

The closed-way branch uses the exact repeated endpoints already used by matching; it does not add interior-node roundabout connectivity.

Evidence

The implementation boundary follows the current OSM Wiki documentation for oneway, closed ways, motorway_link, and junction=circular: fixed yes/no/-1, deprecated 1/0, ordered closed geometry, and the limited roundabout/motorway implication boundary.

The external candidate matrix executes the production normalization helper and generated offline.Way runtime accessor. It passes 100 repetitions, followed by:

Check Result
go test ./... Pass
go test -race ./... Pass
go vet ./... Pass
go build ./... Pass
git diff --check Pass

Rollout and scope limits

The offline Cap'n Proto schema remains wire-compatible, but generator and runtime behavior are version-coupled for closed ways. Deploy the runtime before distributing regenerated tiles to older clients. Existing tiles remain unchanged until regenerated.

This does not implement reversible, alternating, conditional, or mode-specific restrictions; infer motorway links; add interior roundabout connections; validate turn-restriction relations; or measure production prevalence. Current main's separate legal-candidate fallback correction is unchanged by this diff.

@FrogAi
FrogAi force-pushed the codex/preserve-one-way-generation branch from a249fc9 to c8769f6 Compare August 10, 2026 03:03
@FrogAi
FrogAi force-pushed the codex/preserve-one-way-generation branch from c8769f6 to def5848 Compare August 10, 2026 03:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant