User clarified: the X-swap should be in the ARRANGEMENT (east
tiles on screen right), NOT in the image (so map content is
readable). Previous attempts had it the other way around.
Combined state:
- canvasX = -perp + ... (X-swap): east (1102) on screen right,
west (1098) on screen left. x increases left to right.
- drawImage with positive width: no image X-flip. Map content
reads normally, place names not mirrored.
- Labels in normal orientation.
So the X mirror is in the corridor arrangement, not in the
satellite image content. The user can read the map normally.
Final state per user request (KEIN X-Swap, KEIN X-Flip):
- canvasX = (perp + halfPerp + 0.5) * TILE_SIZE: east (1102)
at canvasX 128 (left), west (1098) at canvasX 1152 (right).
Natural order with no swap.
- drawImage with positive width and height: map content reads
normally, no X-flip on the image.
- Labels in normal orientation (no mirrorLabel).
Map is now fully natural: no X swap, no X flip, no mirror label.
Both the arrangement and image content are in standard orientation.
The user wants:
- Natural order arrangement (canvasX = perp + ...): east (1102)
on left, west (1098) on right
- X-mirrored image (NS-mirror): within each tile, the image east
appears on the left of the tile (natural map orientation)
Combined state:
- canvasX = (perp + halfPerp + 0.5) * 256: natural order
- drawImage with negative width: X-flip (NS-mirror)
- All labels in normal orientation (no mirrorLabel)
This matches the user's description: 'die anordnung passt' (arrangement
correct) and 'der x-flip ist immer noch falsch' (image was still
mirrored, now correctly mirrored).
User wanted NO X-swap and NO image X-flip:
- canvasX = (perp + 2.5) * 256 (no negation): east (perp=-2)
at canvasX 128 (left), west (perp=+2) at canvasX 1152 (right)
- Image drawn with positive width (no X-flip): map content
reads normally (place names, street names not mirrored)
The X coordinates read in their natural geographic order:
- left = high x (east), right = low x (west)
If the user is observing from a south-facing view (cockpit facing
back), their right is the world's left (east), so they see
high x on their right (world's left). x still reads correctly
when facing the same direction as the flight.
The arrangement is now back to the natural order with no
swapping in either direction.
Add explicit X-swap marker comment so the user can verify they're
seeing the new build. Bump canvas width by 2*256 padding so the
X labels (drawn at canvasX + 244) are within the canvas even for
the rightmost drawn tile (east, perp=-2 -> canvasX 1152, label
at 1396). With wider canvas (1792 vs 1280), labels are visible
and the corridor is centred.
The user wants the original tile content (map) to be readable
normally, not X-mirrored. The X-swap arrangement (canvasX = -perp
+ ...) places east tiles on the right of the screen, so X coordinates
read naturally left to right when scanning the corridor.
Combined state:
- Map content (image): drawn with normal orientation (no X-flip)
- Arrangement: east on right, west on left (X-swap)
- Labels: drawn in normal orientation in the corners
- Y-swap: north tiles (lng=+12) at canvas top -> screen top
The user wanted the tile content to be NS-mirrored (X-flip
on the image) so the corridor orientation matches. The labels
are drawn separately in normal orientation, so they read
normally. Now the arrangement has:
- canvasX = -perp + ... (X-swap): east tiles on screen right
- Image X-flipped (NS-mirror): image east at left of tile
- Labels in corners drawn normally: x=1102, y=707 readable
Combining these, the user looking at the screen sees:
- screen left: west tiles (low x), with image west on the right
- screen right: east tiles (high x), with image east on the left
- All labels readable
So the X coordinates read correctly when the eye scans left
to right across the corridor, and the image content is
NS-mirrored to match the corridor's direction of travel.
The user wanted the image content to be readable (not X-flipped).
The X-swap arrangement (canvasX = -perp + ...) already places east
tiles on the right side of the screen, so the X arrangement
reads naturally left to right without needing the image to be
flipped.
The image is now drawn with positive width and height, so
place names, street names, and the coordinates labels (x=NNN,
y=NNN) are all readable. The X-swap arrangement positions the
tiles so that:
- west tiles (low x) drawn at canvas left
- east tiles (high x) drawn at canvas right
So the X coordinates increase left to right when reading the
corridor from screen left to screen right.
User wanted the image to be X-mirrored (NS-mirror, so place
names on a map are correctly mirrored for the corridor
orientation), but the text labels to be readable normally.
Now labels are drawn in normal orientation:
- N at top-left
- S at bottom-left
- y at top-right
- x at bottom-right
The text is no longer reversed. With the corridor's X-swap
arrangement, this means:
- screen left = west tiles (low x)
- screen right = east tiles (high x)
- within each tile, the image is X-mirrored, but the text
inside is readable
The drawImage call uses width=-TILE, height=+TILE, which is an
X-only horizontal mirror. The old comment said '180 degrees'
which implied both axes flipped; the code is only horizontal.
NS axis = vertical axis, mirror across it = horizontal mirror.
Current state matches the user's observation: tile content
is NS-mirrored, X arrangement goes low->high left to right.
Carto Voyager was returning 'API Key required' content for the
user (likely rate-limited or IP-blocked by Carto). Switched to
ESRI World_Street_Map which has CORS-friendly tiles with plenty
of place names and street labels.
URL format is different from Carto: {z}/{y}/{x}.jpg (y before x,
jpg not png). Updated the build to match. The local /esri/
proxy in default.conf handles the upstream CORS-incompatibility
by adding permissive CORS headers and a proper User-Agent.
Direct fetching from a.basemaps.cartocdn.com was returning
stripped/missing CORS headers in the user's browser, blocking
the img.src load. Even with cache-busters the failure persisted.
Solution: local nginx proxy at /carto/ that forwards to the
upstream and always adds Access-Control-Allow-Origin: *.
Key detail: the 'resolver' directive is required inside the
proxy_pass location block so nginx can resolve the upstream
hostname. Without it, the location block silently fails (the
'/' location falls through to try_files ... =404, and the
~*\.(png|jpg)$ regex also matches and silently fails for GETs).
Also added 'location ^~ /carto/' to give prefix matching strict
priority over the .png regex match that was stealing the request.
JS now uses /carto/voyager/ (relative URL through the same
origin) so CORS preflight is not even needed.