Repository navigation
TrailView ground plan: junction records and the stop-mouth route rule - #3186
Conversation
A junction label's owner word names its junction record: the node and, per arm, its record line, its samples from the node to the first past its seam, its direction at the node and two flags (host, stop). The corners, the far paint, the heights' arms and the stop flag of the mouth read the record; junction labels have no host and other lines and no paint segments in the bins. MAGIC 0x4f42_5209. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ines A host line that goes on through the junction as a guest arm keeps its frame there, and a junction whose material line is a guest's frames its corners by that line too, as the bin search did. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The paint of a junction face reaches past the face's seam; there the host line runs on straight as its own segment, not round its last sample. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…record In a junction face with a stop arm, the route arms divide the plane about the node into sectors. In a sector with a stop arm a point keeps the junction's look on a route arm's stroke (flat at the node) or in the bounded mitre where the two route arms that bound the sector meet, within 2 cm; elsewhere it wears the nearest stop arm's look in that arm's frame. The rule reads the junction record, near and far, and replaces the search of the bin's segments. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the
|
…ines The record names the frame lines (hosts, near also the material line; every arm for soil), and the bin gives their segments, as before the record: the bins list every segment of a junction's arm lines that can be nearest to a point of the bin, so the frame equals the base's by construction. The arm ranges and their extra segment no longer give frames. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The sector test already finds the stop arms between the two route arms; the frame and the look take the nearest of those. A test keeps the route rule's mitre corner and the arms' own edges beside a mouth. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…stop mouth Each route arm's facing edge at the node runs straight to the other arm's facing edge at its seam. Two arms of different widths (c11) meet without a step; where both are as wide, the taper lies within the strokes and the mitre. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hs at a stop mouth" This reverts commit 3c711fd. The taper's straight chords leave a curved arm's edge (delta review): c11 stays an owner decision. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
From the plan after the 2026-11-07 review of #3096 (special cases): Problem. Proposal. No finish list in code. A guest is a stop arm when it is not a host, its pair's mouth is not Effect on the fixture (1,041 junctions): stop arms 294 → 388 with the Proof. One predicate and its test (a pavers path at a service road, an asphalt cycleway at a gravel track); the census shots of the changed junctions, top and eye height, ground-plan | new; the two mouth flights ( Also on this PR: Out of scope here: R2 and R3 of the junction-look diagnosis (every arm keeps its own look; no frame interpolated across arms). They are one later slice on the same functions. |
A guest stops at its host where its pair's mouth in plan.json is stop, its corners are round, and its finish or material differs from the best host's or its finish is in tread_finishes of plan.json. The hard-coded unpaved list goes: paving-stone paths at a service road and asphalt cycleways at a gravel track keep their own look up to the route's edge. A paved guest of the host's look needs no mouth; a soil one keeps its tread as before. A reach pair keeps the junction's look. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A line of a path class (group path or steps) carries PATH in its finish word. line_look reads that flag: a dirt or grass path wears a trail's tread and a dirt or grass track wears dirt, as lookOf of section.ts. The corners and the stop mouth no longer guess "path" from a half-width under PATH_HALF_M = 1.2. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… curve Where the facing edge corner of one route arm at the node lies past the other's facing edge line (two arms of different widths that run on straight), the other arm's stroke widens on the stop side by that much at the node, back to its own width at its seam, along its own centre line; the mitre takes the widened edges. Where the two arms are as wide, nothing widens. The test port has the rule, with a case of two widths. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fields apart Bit 11 is the walls branch's WALL flag, and water plans bits 12 and 13. A const assert fails the build where two fields of a line's finish word overlap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The junction record (#3186) and the load order (#3204) join the outline slopes. The head keeps the junction table at words 12 and 13; the outline edges move to word 14 (HEAD 15). WALL (bit 11) joins the finish word's disjoint fields beside PATH (bit 14). MAGIC 0x4f42_5211. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What
Each records block gets a junction record (JR) per junction that a label names. A stop mouth uses it: the route keeps its true edge, and the stop look no longer searches the bin.
records::encodewrites the JR: the node, and per arm its record line, its samples from the node to the first sample past its seam, its unit direction at the node and two flags (host, stop). Head word 12 is the offset of the JR table and word 13 the JR count (HEAD= 14). A junction label's word 1 holds its JR index: label → table → JR, two reads. Junction labels have no host and other lines;records::ownergives the checks and the mesh the graph's junction id.heights::arms_ofandh_arms_ofread a junction's arms from the JR.corner_lookandmodel_pointread a junction's frame lines from the JR (hosts; near also the material line; soil every arm) and their segments from the bin, as before the JR. The bins keep the paint segments of the junction's arm lines. So the frame equals the base's by construction.mouthLabelsreads the stop flag from the JR.terrain/mouth.wgsl, near and far). In a junction face with a stop arm, the route arms divide the plane about the node into sectors. In a sector with a stop arm, a point keeps the junction's look on a route arm's stroke (flat end at the node) or in the mitre where the two route arms that bound the sector meet (behind both node lines, limit 4 h), within 2 cm. Every other point of the sector wears the nearest stop arm of that sector, in that arm's frame. The bin search for the mouth,STOP_ARM,other_line,m_arm_line,m_otherand the dead branch for three host lines go.mouth.wgslas of 8946986 (test code only) keeps the mitre's corner and each arm's own edge beside a mouth at a bend. A vitest forsplitMouths.MAGIC0x4f42_520d. ground-plan's history used 5209 to 520b; the walls pull request ground-plan GP3 follow-up: walls from a slope budget (draft, not ready) #3185 takes 520c. The one that lands second takes the next value at its rebase. The commits before 2d24c46 still write 0x4f42_5209.Commits
19ce4ac52the record, its writer and readers.5a8240c43,9cfc02ed5frame fixes from the first pixel compare.9174776abreplaces both (see below).73009d72athe route rule.2d24c464cMAGIC0x4f42_520d.9174776abthe frame from the bin's segments of the JR's lines;89469869cthe stop look from the sector's own stop arms, and the route-rule test.3c711fd76a c11 taper, reverted by0053ed227: its straight chords leave a curved arm's edge (delta review: up to 1.30 m, spikes).0053ed227is the reviewed state89469869c.6838a13edstops()from table values (special case 1, see below).8d1a797bfthe trail look from the line's class, not fromPATH_HALF_M(special case 2, see below).e2e561277PATHmoves to bit 14 (M_PATH16384): bit 11 is the walls branch'sWALL, and water TrailView ground plan GP14 slice 1: line water (records, level, banks, culvert zones) #3177 plans bits 12 and 13. A const assert fails the build where two fields of a line's finish word overlap; a new flag joins its list.f227fcc70c11 widening (owner approved): the narrower route arm of a stop mouth widens along its own curve (cherry-pick of 9707268 fromclaude/gp-junction-taper).Special cases removed (commits 7 and 8)
stops()from table values. A guest arm getsARM_STOPwhere its pair's mouth inplan.jsonisstop, its corners are round, and either its look (finish and material) differs from the best host's, or it is a soil guest whose finish is in the newplan.jsonlisttread_finishes(gravel, dirt, grass, path). The hard-coded unpaved list in code goes.reachpair keeps the junction's look; it can join later if renders show the need.tread_finishes: without it, 13 same-look soil guests (gravel path at a gravel service road, dirt path at a dirt track) lose the flag. They then take the interpolated corner frames, and their treads tear (fault 2.2 of the diagnosis). With the list, those guests are pixel-equal to the base.pics/c09-service-path-T.jpg,pics/f1-c09-top.jpg): the paving-stone paths keep pavers up to the service road's edge.pics/p07.jpg): its hosts are gravel footways and its guest an asphalt footway, apath/pathpair with mouthreach. A trial with the reach pairs (stop arms 488) fixed p07 but cut soil treads with straight sector edges at p06, p08, p09 (pics/reach-*.jpg, labelled base | trial).The trail look from the class. A line of a path class (group
pathorstepsinroads.json) has the flagPATH(bit 14) in its finish word.line_lookreads it, aslookOfofroads/section.tsreads the line's kind.PATH_HALF_M= 1.2 and the half-width guess go fromplan/corners.wgslandplan/mouth-in.wgsl. The width guess still lives inground/roads.wgsl(the drawn ground, outside the plan). On the fixture 2 ways change look, both dirt with a half-width of 1.5 m: a cycleway and a path with awidthtag. They now wear a trail's tread, not a track's ruts (pics/t2-cycleway-dirt.jpg,pics/t1-path-dirt-wide.jpg).Why the first frame changed pixels
Commit 1 first read a junction's frame from the arm ranges in the JR (node to the first sample past the seam). The base read it from the bin, which lists every segment of the frame lines that can be nearest to a point of the bin: the nearest point of the whole line. A point whose nearest point on the line lies past the range got a round frame there. The far paint shows it most, because it paints texels outside the face with the junction's label: a dirt path broke at two stub junctions near conn-path-off-road, and the culvert of mouth-stream had a notch.
9174776abreads the frame from the bin again.Checks
On 8d1a797 (the head):
cargo test -p obc-ground-plan: 102 passed, on both commits.cargo clippy -p obc-ground-plan --all-targets -- -D warnings: clean.cargo fmt --all.check-bytes.sh: 256 of 256 (the checker again hung at exit after it printed).npx vitest run src/lib/trailview: 408 passed.npm run check: 0 errors.npm run check:wgsl: 69 valid.tread_finishesparse is most of the +313 B). Gzipped 691,166 B against 704,512 B.pics/v14-top-overlay-base-c2.png). The 5 same-look soil views (l1..l5): 5 of 5 equal.On 8946986 (the review fixes; the taper changes only
mouth.wgsl):cargo test -p obc-ground-plan: 102 passed.cargo clippy -p obc-ground-plan --all-targets -- -D warnings: clean.cargo fmt --all.check-bytes.sh: 256 of 256.npx vitest run src/lib/trailview: 408 passed.npm run check: 0 errors.npm run check:wgsl: all valid, the mouth composition too.Left out: a full
obc test affected; develop shots;road-views-far.json.Measurements
Records over the fixture: near 15,855,809 words (ground-plan 15,835,684, +20,125, +0.13 %); far 13,178,354 (13,158,229, +20,125, +0.15 %). The bins keep the junction paint segments; the JR adds 1,478 records, 4,567 arms.
eps= 2 cm is a chosen value: the face's edge lies up to about 2 cm outside a stroke (snap and chords). The fixture's hairline counts (stop-look points with no other stop point 6 cm away, 249 owned stop junctions, 5 cm grid) fall steadily, with no knee: 289 at 0 cm, 122 at 1 cm, 88 at 2 cm, 56 at 3 cm, 45 at 5 cm, 24 at 10 cm.Frame cost,
flight.mjs --gpu, terrain pass median (ms), ground-plan | 2d24c46, 3 alternating runs:One v14-pass run on 8946986: 2.36 (ground-plan 2.33 in the same pair).
Pictures
/media/timo/OSM1/tmp/ground-plan/junctions/impl/pics/(INDEX.mdhas a verdict per picture). Commits 7 and 8:/media/timo/OSM1/tmp/ground-plan/junctions/sc/pics/(base | head crops).v14-top-overlay-base-flat-taper.png, andc2/v14-top-diff.png.diff/c1eq/; 47 views: the reviewer's 21 eye views against their controlbase3, and the earlier differing top and mouth views): 39 equal. The far-paint path break and the culvert notch are gone (pics/cpor-far150-base-c1c-fix.jpg). Left: c16-eye, footway-eye, conn-road-into-track-top and side-15m are noise (a second ground-plan run differs the same way); hp-15m is 13 px noise and 7 px real. Small, real, cause not found: b-steps-eye 68 px on a distant ridge (the same in every branch build), bridge-eye 38 px (single pixels on the parapets), v14-far150 4 px.c11 (owner approved: widening, commit 9)
c11: two roads of 2 m and 3 m half-width meet at the node with gravel tracks on both sides. Flat stroke ends gave a ~1 m square step on each side of the node. Now, where the facing edge corner of one route arm lies past the other's facing edge line, the other arm's stroke widens on the stop side by that much at the node, back to its own width at its seam, along its own centre line; the mitre takes the widened edges. Where the two arms are as wide, nothing widens. The Rust test port has the rule and a case of two widths.
check:wgsl69 valid, vitest 408, probe as above (0.119 mm, 0 kinds differ), size unchanged (WGSL only: raw 1,800,971 B, 1,269 B left).sc/pics/c11.jpg). v14 stays on the owner's line.Open
lastfrom each block's region candidates; the review found 1 of 363, with no pixel change).Public docs: unchanged.
Mode: change #3182
Requirements: none
🤖 Generated with Claude Code