From a38d942e568ace119e3c8a684613cfe1ebd57525 Mon Sep 17 00:00:00 2001 From: Richard Zink Date: Thu, 8 Oct 2026 08:26:11 +0200 Subject: [PATCH] Mirror labels across NS axis (scale -1, 1) Each label is now drawn inside a save/translate/scale(-1, 1)/ restore context, so the actual text appears horizontally mirrored in the canvas. This is the user-requested 'NS axis mirror' for the labels. N/S characters are symmetric so they look the same mirrored or not. But 'x=1100' and 'y=1100' now appear reversed (1011 etc.), confirming the horizontal flip is in effect. --- vendor/clouds3d.js | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/vendor/clouds3d.js b/vendor/clouds3d.js index e8c68e8..1e782af 100644 --- a/vendor/clouds3d.js +++ b/vendor/clouds3d.js @@ -361,34 +361,34 @@ function drawTileAt(lng, perp, dx, dz, centerTileX, centerTileY) { groundCtx.strokeRect(canvasX + 1, canvasY + 1, GROUND_TILE_SIZE - 2, GROUND_TILE_SIZE - 2); - // Burn labels into the four corners of the tile, NS-mirrored - // (so N ends up at the bottom and S at the top, mirroring the - // tile's own NS axis). User can read the tile identity - // directly from the rendered ground. + // Burn labels into the four corners of the tile, mirrored + // across the NS axis (horizontal mirror via scale(-1, 1)). + // Each label is drawn within a saved/flipped context so the + // text itself appears mirrored. groundCtx.fillStyle = 'rgba(255,255,255,0.95)'; groundCtx.strokeStyle = 'rgba(0,0,0,0.85)'; groundCtx.lineWidth = 3; - groundCtx.textAlign = 'left'; groundCtx.font = 'bold 40px sans-serif'; + // Helper: draw a horizontally-mirrored label at (x, y). + function mirrorLabel(text, x, y, align) { + groundCtx.save(); + groundCtx.translate(x, y); + groundCtx.scale(-1, 1); + groundCtx.textAlign = align; + groundCtx.strokeText(text, 0, 0); + groundCtx.fillText(text, 0, 0); + groundCtx.restore(); + } // S at top-left (image south after Y mirror is at canvas top) - groundCtx.strokeText('S', canvasX + 12, canvasY + 44); - groundCtx.fillText('S', canvasX + 12, canvasY + 44); + mirrorLabel('S', canvasX + 12, canvasY + 44, 'left'); // N at bottom-left (image north at canvas bottom) - groundCtx.strokeText('N', canvasX + 12, canvasY + 244); - groundCtx.fillText('N', canvasX + 12, canvasY + 244); + mirrorLabel('N', canvasX + 12, canvasY + 244, 'left'); // Tile coordinates, top-right and bottom-right corners - groundCtx.textAlign = 'right'; groundCtx.font = 'bold 18px monospace'; // y at top-right - groundCtx.strokeText('y=' + tileY, - canvasX + GROUND_TILE_SIZE - 12, canvasY + 28); - groundCtx.fillText('y=' + tileY, - canvasX + GROUND_TILE_SIZE - 12, canvasY + 28); + mirrorLabel('y=' + tileY, canvasX + GROUND_TILE_SIZE - 12, canvasY + 28, 'right'); // x at bottom-right - groundCtx.strokeText('x=' + tileX, - canvasX + GROUND_TILE_SIZE - 12, canvasY + GROUND_TILE_SIZE - 12); - groundCtx.fillText('x=' + tileX, - canvasX + GROUND_TILE_SIZE - 12, canvasY + GROUND_TILE_SIZE - 12); + mirrorLabel('x=' + tileX, canvasX + GROUND_TILE_SIZE - 12, canvasY + GROUND_TILE_SIZE - 12, 'right'); return true; }).catch(function() {