Track plans read as outlines, not hatching

Nearly every track is one model repeated: cn3, a wall bar whose gauge
image is two closed 25x5 rectangles. Five metres of wall thickness is
finer than the plan can resolve, so each bar was landing as two parallel
lines plus two end caps - several hundred times over, which is the
hatching that swamped the arenas. Collapse a thin closed quad to the
centreline between its short edges: one stroke for one wall.

Walls stacked to build height coincide seen from above, so draw each
distinct wall once. And drop placements standing alone more than 200
units from any other - fourteen tracks park a single bar at (1200,0,0)
well off the course, and that one placement stretched the frame to
twelve times the width of the track. The four tracks without it are
exactly the four that always framed correctly. A real branch keeps its
neighbours and stays: Paingod's second canyon is sixty bars out at
x=-400.
This commit is contained in:
Cyd
2026-08-07 11:05:16 -05:00
parent 99030e4aac
commit 5135476088
4 changed files with 143 additions and 70 deletions
+74 -63
View File
File diff suppressed because one or more lines are too long
+4 -4
View File
@@ -86,7 +86,7 @@ def era(key):
GAUGE_IDS = {rid for rid, r in TABLE.items() if r['desc'].endswith(': GaugeImage')}
def plan_view(segs, box=900):
def plan_view(segs, box=520):
"""The track's own outlines, straight down, as an alpha mask."""
pts = [p for seg in segs for p in seg]
xs = [p[0] for p in pts]
@@ -171,9 +171,9 @@ for key in ORDER:
kin = [k for k in twins.get(sig, []) if k != key]
twin = ('<p class="twin">Same footprint and instance count as '
+ ', '.join(tracks[k]['name'] for k in kin) + '</p>') if kin else ''
short = ('<p class="twin">%d of %d placements carry map art; the rest the '
'map screen does not draw either</p>' % (t['drawn'], t['instances'])
) if t['skipped'] else ''
short = ('<p class="twin">%d of %d placements are drawn; the rest carry no '
'map art or stand alone off the course</p>'
% (t['drawn'], t['instances'])) if t['skipped'] else ''
art = ('<span class="plan__img" role="img" aria-label="%s plan view" '
'style="--art:url(%s);--ar:%d/%d"></span>'
% (html.escape(t['name']), t['art'], t['aw'], t['ah'])) if t['art'] else ''
+54 -3
View File
@@ -100,6 +100,29 @@ def instances(res, addr, size, count, gauge_ids):
return out
def spine(seg):
"""A track is built almost entirely from one model, cn3: a wall bar
drawn as two closed 25x5 rectangles. Five metres of wall thickness is
below the map's own resolution, so drawing the rectangle puts two
parallel lines and two end caps where the wall is one line - and a few
hundred bars of that is the hatching that swamps the plan. Collapse a
thin closed quad to the centreline joining its two short edges: the
same wall, drawn as the single stroke it reads as."""
p = seg[:-1] if len(seg) >= 5 and seg[0] == seg[-1] else None
if not p or len(p) != 4:
return [seg]
import math
edge = [math.hypot(p[(i + 1) % 4][0] - p[i][0],
p[(i + 1) % 4][2] - p[i][2]) for i in range(4)]
if max(edge) == 0 or min(edge) / max(edge) > 0.5:
return [seg] # not a bar - leave it alone
lo = min(range(4), key=lambda i: edge[i])
a, b = p[lo], p[(lo + 1) % 4]
c, d = p[(lo + 2) % 4], p[(lo + 3) % 4]
mid = lambda u, v: tuple((u[k] + v[k]) / 2 for k in range(3))
return [[mid(a, b), mid(c, d)]]
def rotate(q, p):
"""Quaternion (x,y,z,w) applied to a point."""
qx, qy, qz, qw = q
@@ -120,10 +143,29 @@ def track_lines(res, table, map_addr, map_size, map_count):
gauge[rid] = r
segs = []
drawn = skipped = 0
for gid, pos, q in instances(res, map_addr, map_size, map_count, set(gauge)):
placed = instances(res, map_addr, map_size, map_count, set(gauge))
# Fourteen of the eighteen tracks carry a single bar parked at exactly
# (1200, 0, 0), well off the course; the four that don't are the four
# that always framed correctly. One stray placement drags the bounding
# box out to twelve times the width of the course and squeezes the
# track into a sliver, so drop placements that stand alone. A real
# branch - Paingod's second canyon is sixty bars out at x=-400 - has
# neighbours and stays.
def isolated(i):
x, _, z = placed[i][1]
for j, (g, p, _) in enumerate(placed):
if j != i and g is not None and (p[0] - x) ** 2 + (p[2] - z) ** 2 < 200 ** 2:
return False
return True
for i, (gid, pos, q) in enumerate(placed):
if gid is None:
skipped += 1
continue
if isolated(i):
skipped += 1
continue
r = gauge[gid]
img = read_gauge_image(res, r['addr'], r['size'])
if img is None:
@@ -138,5 +180,14 @@ def track_lines(res, table, map_addr, map_size, map_count):
wx, wy, wz = rotate(q, verts[k])
pts.append((wx + pos[0], wy + pos[1], wz + pos[2]))
if len(pts) > 1:
segs.append(pts)
return segs, drawn, skipped
segs.extend(spine(pts))
# Walls are stacked to build height. Seen from above those copies land
# on each other exactly, so draw each distinct wall once.
seen, out = set(), []
for s in segs:
key = tuple(round(v, 1) for p in s for v in (p[0], p[2]))
if key not in seen:
seen.add(key)
out.append(s)
return out, drawn, skipped
+11
View File
@@ -50,6 +50,17 @@
rotated and positioned. A placement whose model has no gauge image is skipped here
exactly as the map screen skips it, which is why a card can say fewer placements
carry map art than the track contains.</p>
<p class="foot">Two things are drawn plainer than the pod draws them, so the plan reads
as an outline. Nearly every track is one model repeated &mdash; <code>cn3</code>, a
wall bar whose gauge image is two closed 25&times;5 rectangles. Five metres of wall
thickness is finer than the plan can resolve, so each bar is collapsed to the
centreline between its short edges: one stroke for one wall, instead of two parallel
lines and two end caps several hundred times over. Walls stacked to build height land
on each other seen from above, and are drawn once. Placements standing alone more than
200 units from any other are dropped &mdash; fourteen tracks park a single bar at
(1200,&nbsp;0,&nbsp;0) far off the course, and one stray placement stretches the frame
to twelve times the width of the track. A real branch keeps its neighbours and stays:
Paingod's second canyon is sixty bars out at x&nbsp;=&nbsp;-400.</p>
<p class="foot">So the walls are the canyon walls and the chambers are real chambers,
but there is still no driving surface: the map draws what lines the route, never the
tarmac. Extent and relief are the span of the drawn outlines in world units, so a