Preserve OSM one-way direction during generation - #105
Merged
Merged
Conversation
FrogAi
force-pushed
the
codex/preserve-one-way-generation
branch
from
August 10, 2026 03:03
a249fc9 to
c8769f6
Compare
FrogAi
force-pushed
the
codex/preserve-one-way-generation
branch
from
August 10, 2026 03:21
c8769f6 to
def5848
Compare
FrogAi
force-pushed
the
codex/preserve-one-way-generation
branch
from
September 4, 2026 21:28
def5848 to
07a4cfc
Compare
FrogAi
added a commit
to FrogAi/mapd
that referenced
this pull request
Sep 4, 2026
Retain the original PR commits and the tested rewrite. The resulting file tree is identical to 07a4cfc.
Replace the earlier implementation with the simplified version.
FrogAi
force-pushed
the
codex/preserve-one-way-generation
branch
from
September 4, 2026 21:50
df7d771 to
bfcfe77
Compare
This was referenced Sep 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The upstream generator records only
oneway=yes, so legacy1, reverse-1, and untagged roundabouts/motorways could lose their fixed direction in tiles. This change accepts those static cases, reverses stored nodes for-1, and swaps both directional speed pairs with the reversal. Explicit primary-tag overrides remain effective.The existing one-way boolean and ordered node list remain the representation. A narrow runtime fix also lets a closed one-way be entered at its repeated endpoint in stored order.
Deploy the runtime fix before publishing regenerated tiles. Existing tiles need regeneration to gain the newly handled tags. This change does not add conditional or dynamic one-way direction support.
Representation, rationale, reproducible checks
Representation and tag behavior
The existing tile format already stores a one-way boolean and an ordered node list. Normalizing fixed reverse ways during generation lets the runtime continue interpreting stored forward order as the legal direction. No schema change is needed.
onewayvalueyesor1-1junction=roundaboutorhighway=motorwaynoor0reversible,alternating, or unknown explicit valuemotorway_linkorjunction=circularaloneThe defaults run only when the primary tag is absent/empty. They do not override an explicit primary value. The fixed-direction interpretation follows the OSM one-way documentation; conditional/dynamic direction support is outside this change.
Reverse-way metadata
Directional speed tags are relative to OSM node order. Reversing only the nodes would attach the original forward speed to the wrong stored direction, so both directional pairs are swapped together.
oneway=-125 @ (Mo-Fr)/70 @ (Mo-Fr)70 @ (Mo-Fr)/25 @ (Mo-Fr)A closed way repeats its first node at the end of the list. The upstream runtime's endpoint check classifies that shared endpoint as the end, rejecting stored-forward entry on a one-way loop. The narrow fix recognizes the shared endpoint of a closed one-way as forward. Open-way endpoints and closed two-way classification retain their existing behavior.
Verification
Checked head
bfcfe77, treeaa581653eda08616b2511c7d0e4c2c664323368d, against upstream7201c6b4b4ec1b0b9ea21daa8c05b80fdd7e01ee. The production diff is confined to generation and closed-endpoint direction.The complete reproducer below creates all 20 synthetic OSM ways, runs
osmium add-locations-to-ways, calls realGenerateOffline, reads the packed tile, and checks flags, every coordinate, both directional speed pairs, nondirectional metadata, bounds, highway class, endpoint classification, and legal/wrong-way bearings for the reverse way. A second test constructs a two-road tile and calls actualNextWayfor both a closed one-way and a closed two-way.NextWayinto closed one-way02, forwardNextWayinto closed two-way2, backward2, backwardExecuted on 2026-09-05 with Linux amd64, Go 1.25.1, osmium 1.16.0, and libosmium 2.20.0. The actual run used an already populated module cache,
GOPROXY=off,GOSUMDB=off, and a container with networking disabled. Source copies and generated fixtures were isolated from the branch and production data. No production tiles were regenerated or distributed, and no device driving replay was performed. These tests establish the static generation/runtime cases listed above.Combined validation: exact source tree
a4c306906627db3ac7a8ab768651c8628d55465acombines #1019d61f06a1288ec4ea6f74f7d56a3057444316a13, #10320e7c25b054b6399360676a7f539a39b4fbf855c, #105bfcfe77be066634e36054327b20cfa6541063b54, #1078e5e677d1196838069e9665d4e9d962bcc1e116b, #1166fd5bbd6cf617c24a7fefd5e302fd36688a1a63b, #13630e8ce98ea7a4c8401dbb5bfc62120c84fc689e4. The only overlapping file issettings/download.go; the resolution retains #136's selected-row loop and #107's progress publication inside it.On 2026-09-05, combined Linux amd64 tests (including the scratch regression fixtures), race checks, vet and build passed. Under ARM64 emulation, the existing Makefile build stage (
make GO_CAPNP_PATH=/usr/local/go-capnp/std), committed repository tests, vet and both CLI help commands passed with Go 1.25.1;go.mod/go.sumstayed unchanged and the resulting executable is AArch64. The ARM64 run does not include the extra amd64 scratch tests. It used an isolated retained build image, not a new dependency-install/image rebuild or physical device. No production archive payload or live params were accessed. #105 still requires runtime-first rollout before regenerated tiles are distributed.Reproduce from a fresh clone
Save the two complete blocks below beside each other as
reproducer_test.goandreproduce.sh. Requirements are Linux, Bash, Git, tar, Go 1.25.1, and osmium. The runner archives the pinned upstream and current revisions into separate temporary directories, adds only the test file to each copy, runs the assertions, then runs the current focused race check and package vet.The setup command downloads only repository/module dependencies. The actual fixture requires no network or external OSM data. Populate a module cache for both revisions, then the runner explicitly disables dependency fetching:
reproduce.sh:reproducer_test.go: