fix(client): T-1153/T-1152 round 5 — nearest-wrap-image tile draw placement; canonical reset restores the fit zoom and re-fires
The wrapped tile column (Lendel: -6400 canonicalized to 12739) drew at its canonical column — off-canvas right — leaving the mosaic's left third black. nearest_wrap_image() re-expresses a tile column as the wrap-image closest to held_center for DRAWING only (requests/cache keys stay canonical). The draw-position test asserts overlap FRACTION, not bare intersects() — the buggy placement still clipped ~2px of viewport edge at Lendel scale, so intersects() alone would false-pass. The full-zoom-out reset restored center but not the fit zoom, and its 'already there' guard keyed on a lagging field so it could only ever fire once. The guard now also matches tile mode and compares _view_zoom against the freshly computed fit — restoring the FULL canonical transform (center, offset, fit zoom) and re-firing as a continued gesture keeps zooming out (Jeroen's hard condition, both live shapes). +8 revert-verified tests incl. the continued-gesture reset repro; smoke stub gained get_body_radius_km (crash confirmed real under a real driver before fixing). Suites 286 green; gdlint clean.
This commit is contained in:
@@ -744,6 +744,154 @@ func test_district_to_canvas_local_zero_held_n_does_not_crash() -> void:
|
||||
assert_that(result).is_equal(Vector2(5, 5) * CELL_PIXEL_SIZE)
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Live round 5: nearest_wrap_image() — the tile-mosaic WRAP half of "the
|
||||
# mosaic doesn't fully draw" (the left-third-black repro).
|
||||
# =============================================================================
|
||||
|
||||
|
||||
## Live round 5's OWN repro, pinned exactly: Lendel's wrapped tile
|
||||
## canonicalizes to column 12739 (`-6400 mod 19139`) — the CORRECT
|
||||
## request/cache key — but its nearest wrap-image relative to the canonical
|
||||
## origin (held_center.x = 0) is -6400, the actual visible position
|
||||
## immediately west of center.
|
||||
func test_nearest_wrap_image_matches_the_lendel_repro() -> void:
|
||||
var result: int = AtlasWindowGeometry.nearest_wrap_image(12739, 0, 19139)
|
||||
assert_int(result).override_failure_message(
|
||||
"the wrapped tile's nearest wrap-image relative to held_center=0 must be"
|
||||
+ " -6400 (its actual on-screen position), not 12739 (the correct REQUEST"
|
||||
+ " key, but the wrong DRAW position)"
|
||||
).is_equal(-6400)
|
||||
|
||||
|
||||
## The two Lendel tiles that were NEVER wrapped (already close to
|
||||
## held_center) must round-trip unchanged — the fix must not perturb tiles
|
||||
## that were already drawing correctly.
|
||||
func test_nearest_wrap_image_is_a_noop_for_already_nearby_columns() -> void:
|
||||
var cols := 19139
|
||||
for col: int in [0, 6400]:
|
||||
var result: int = AtlasWindowGeometry.nearest_wrap_image(col, 0, cols)
|
||||
assert_int(result).override_failure_message(
|
||||
"column %d is already the nearest wrap-image to held_center=0 — must"
|
||||
+ " be returned unchanged" % col
|
||||
).is_equal(col)
|
||||
|
||||
|
||||
## The result must always be a LEGAL wrap-image of the canonical column —
|
||||
## i.e. `result mod cols == canonical_col mod cols` — regardless of which
|
||||
## image is nearest. This is the correctness invariant the whole function
|
||||
## exists to preserve: re-expressing a column for DRAWING must never change
|
||||
## WHICH district it actually refers to.
|
||||
func test_nearest_wrap_image_preserves_the_canonical_identity() -> void:
|
||||
var cols := 19139
|
||||
for held_col: int in [-50000, -1, 0, 1, 9569, 19138, 50000]:
|
||||
var result: int = AtlasWindowGeometry.nearest_wrap_image(12739, held_col, cols)
|
||||
assert_int(posmod(result, cols)).override_failure_message(
|
||||
"nearest_wrap_image(12739, %d, %d) = %d must still canonicalize back"
|
||||
+ " to 12739 — it may only pick a DIFFERENT wrap-image, never a"
|
||||
+ " different district" % [held_col, cols, result]
|
||||
).is_equal(12739)
|
||||
|
||||
|
||||
## The chosen wrap-image must be the CLOSEST one to held_center — never
|
||||
## farther than half the circumference away (otherwise a different
|
||||
## wrap-image would have been nearer).
|
||||
func test_nearest_wrap_image_is_within_half_circumference_of_held_center() -> void:
|
||||
var cols := 19139
|
||||
for canonical_col: int in [0, 1, 9569, 12739, 19138]:
|
||||
for held_col: int in [-30000, -500, 0, 500, 25000]:
|
||||
var result: int = AtlasWindowGeometry.nearest_wrap_image(canonical_col, held_col, cols)
|
||||
var distance: int = absi(result - held_col)
|
||||
assert_int(distance).override_failure_message(
|
||||
(
|
||||
"nearest_wrap_image(%d, %d, %d) = %d is %d districts from"
|
||||
+ " held_center — must never exceed half the circumference"
|
||||
+ " (%d), or a closer wrap-image exists"
|
||||
)
|
||||
% [canonical_col, held_col, cols, result, distance, cols / 2]
|
||||
).is_less_equal(cols / 2)
|
||||
|
||||
|
||||
## `cols <= 0` (no-radius bodies, which never tile per compute_tile_grid()'s
|
||||
## own doc) must be a safe no-op passthrough — no periodicity to resolve.
|
||||
func test_nearest_wrap_image_zero_cols_is_a_passthrough() -> void:
|
||||
var result: int = AtlasWindowGeometry.nearest_wrap_image(12739, 0, 0)
|
||||
assert_int(result).is_equal(12739)
|
||||
|
||||
|
||||
## The coordinator's own draw-position counterpart to
|
||||
## test_compute_tile_grid_tiles_are_all_canonicalized(): the wrapped tile's
|
||||
## DRAW rect (via district_to_canvas_local(), fed through
|
||||
## nearest_wrap_image() the way _draw_tile_mosaic() now does) must land
|
||||
## SUBSTANTIALLY on-canvas when the view covers the whole body — the exact
|
||||
## Lendel shape (whole-body fit at entry, held_center at the canonical
|
||||
## origin). A bare `Rect2.intersects()` check is NOT discriminating enough
|
||||
## here: at Lendel's own whole-body-fit scale, the BUGGY placement (feeding
|
||||
## the canonical column directly) happens to clip the viewport edge by only
|
||||
## a couple of px (confirmed by hand-computation — the tile-grid's own
|
||||
## edge-to-edge tiling means a full-circumference shift lands almost
|
||||
## exactly one screen-width away, so `intersects()` alone would pass on a
|
||||
## near-miss that still reads as "the left third is black" visually).
|
||||
## Asserting a MEANINGFUL overlap FRACTION (at least half the tile's own
|
||||
## area) is what actually distinguishes "correctly drawn" from "barely
|
||||
## clipping the edge."
|
||||
func test_wrapped_tile_draw_rect_lands_substantially_on_canvas_at_whole_body_view() -> void:
|
||||
var radius_km := 6238.4 # GJ380c (Lendel) — the live-repro body
|
||||
var extent: Dictionary = AtlasDescendGeometry.district_extent(radius_km)
|
||||
var cols: int = int(extent["cols"])
|
||||
var held_center := Vector2i.ZERO
|
||||
var held_n: int = cols # enter_orbital()'s own whole-body held_n
|
||||
var tile_n: int = AtlasWindowGeometry.TILE_N
|
||||
var half_tile: float = float(tile_n) * 0.5
|
||||
|
||||
# The whole-body fit zoom/viewport (matching enter_orbital()'s own fit).
|
||||
var viewport := Vector2(1600.0, 900.0)
|
||||
var fit: Dictionary = AtlasWindowGeometry.fit_window_view(
|
||||
viewport, held_n, CELL_PIXEL_SIZE, 0.0001, 64.0
|
||||
)
|
||||
var view_zoom: float = fit["zoom"]
|
||||
var view_offset: Vector2 = fit["offset"]
|
||||
|
||||
# The wrapped tile's own canonical center — mirrors compute_tile_grid()'s
|
||||
# own dedup/canonicalize step for Lendel's westmost tile.
|
||||
var wrapped_raw_col := -6400
|
||||
var canonical_col: int = posmod(wrapped_raw_col, cols)
|
||||
|
||||
var draw_col: int = AtlasWindowGeometry.nearest_wrap_image(canonical_col, held_center.x, cols)
|
||||
var tile_top_left := Vector2(float(draw_col) - half_tile, 0.0 - half_tile)
|
||||
var local_origin: Vector2 = AtlasWindowGeometry.district_to_canvas_local(
|
||||
tile_top_left, held_center, held_n, CELL_PIXEL_SIZE
|
||||
)
|
||||
var extent_px: float = float(tile_n) * CELL_PIXEL_SIZE
|
||||
|
||||
# Canvas-local -> screen space: _canvas.position = view_offset,
|
||||
# _canvas.scale = view_zoom (AtlasWindowViewer._apply_transform()'s own
|
||||
# transform, mirrored here since this is a pure-geometry test with no
|
||||
# live Control/Node2D tree).
|
||||
var screen_top_left: Vector2 = view_offset + local_origin * view_zoom
|
||||
var screen_extent: Vector2 = Vector2(extent_px, extent_px) * view_zoom
|
||||
var tile_rect := Rect2(screen_top_left, screen_extent)
|
||||
var viewport_rect := Rect2(Vector2.ZERO, viewport)
|
||||
|
||||
var overlap: Rect2 = viewport_rect.intersection(tile_rect)
|
||||
var tile_area: float = screen_extent.x * screen_extent.y
|
||||
var overlap_fraction: float = 0.0
|
||||
if tile_area > 0.0:
|
||||
overlap_fraction = (overlap.size.x * overlap.size.y) / tile_area
|
||||
|
||||
assert_float(overlap_fraction).override_failure_message(
|
||||
(
|
||||
"the wrapped tile's draw rect %s overlaps the viewport %s by only"
|
||||
+ " %.1f%% of its own area — must be at least 50%% when the view"
|
||||
+ " covers the whole body. This is live round 5's 'left third of the"
|
||||
+ " mosaic is black' repro: drawing the CANONICAL column (%d) directly"
|
||||
+ " (without nearest_wrap_image()) places this tile off-canvas RIGHT"
|
||||
+ " instead of its true position on the LEFT"
|
||||
)
|
||||
% [tile_rect, viewport_rect, overlap_fraction * 100.0, canonical_col]
|
||||
).is_greater_equal(0.5)
|
||||
|
||||
|
||||
## The core contract this function exists for: recomputing `_view_offset` so
|
||||
## a KNOWN screen point continues to map to canvas-local
|
||||
## `new_held_n/2 * cell_px` (the new window's own center) — i.e. feeding the
|
||||
|
||||
Reference in New Issue
Block a user