From b3efcfb7a2f7aebe9ba678bb00416cead6e27132 Mon Sep 17 00:00:00 2001 From: German Khokhlov Date: Wed, 4 Nov 2026 18:12:17 +0400 Subject: [PATCH] Build the Navara weather shell without the Cesium SDK: angles from geo, the surface extent in radians Since the weather layer stopped handing Navara the Cesium global, the shared shell read ContextLimits, Math and Rectangle from an undefined SDK and drew nothing on Navara (qa-weather-engine-switch timed out). On Navara the texture limit stays unset, as Cesium's never-created context left it. --- src/layers/weather/shellRendering.js | 16 +++++++-- src/layers/weather/shellRendering.test.mjs | 39 ++++++++++++++++++++++ 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/layers/weather/shellRendering.js b/src/layers/weather/shellRendering.js index b20a3711a..bff4705ae 100644 --- a/src/layers/weather/shellRendering.js +++ b/src/layers/weather/shellRendering.js @@ -2,6 +2,7 @@ import { acquireWeatherImage } from './infraredImage.js'; import { imageryHostStatus } from './imageryHost.js'; import { WEATHER_DETAIL_SIZE, WEATHER_IMAGE_SIZES } from './source.js'; import { msg } from '../../i18n/index.js'; +import * as geo from '../../geo/index.js'; /** Metres above the ellipsoid. Lower shells draw first, so lightning draws last. */ export const WEATHER_SHELL_HEIGHTS = Object.freeze({ @@ -317,7 +318,8 @@ export function createShellSurface({ } function fitTexture(cesium, { width, height }) { - const limit = cesium.ContextLimits?.maximumTextureSize; + // Cesium's limit once its context exists; a Navara shell has no SDK. + const limit = cesium?.ContextLimits?.maximumTextureSize; // Halve, down to 1024 px wide, on devices with a smaller texture limit. while (limit > 0 && width > limit && width > 1024) { width /= 2; @@ -574,7 +576,7 @@ export function createWeatherShell({ /** Recompute the window from the camera's ground footprint; returns whether it changed. */ function computeView() { const rectangle = detailed ? viewRectangle() : null; - const degrees = cesium.Math.toDegrees; + const degrees = geo.math.toDegrees; const footprint = rectangle && { west: degrees(rectangle.west), south: degrees(rectangle.south), @@ -688,7 +690,15 @@ export function createWeatherShell({ viewer, cesium, height, - rectangle: cesium.Rectangle.fromDegrees(west, south, east, north), + // A Navara surface reads the four radians; Cesium gets its Rectangle. + rectangle: cesium + ? cesium.Rectangle.fromDegrees(west, south, east, north) + : { + west: geo.math.toRadians(west), + south: geo.math.toRadians(south), + east: geo.math.toRadians(east), + north: geo.math.toRadians(north), + }, onSettled: () => commit(frame), }); next.bounds = frame.bounds; diff --git a/src/layers/weather/shellRendering.test.mjs b/src/layers/weather/shellRendering.test.mjs index ad65dcef2..e56a57c5f 100644 --- a/src/layers/weather/shellRendering.test.mjs +++ b/src/layers/weather/shellRendering.test.mjs @@ -1502,3 +1502,42 @@ test('global infrared keeps one full-extent image; detail images halve for small }); small.shell.clear(); }); + +test('a Navara shell runs without the Cesium SDK and hands its surface the extent in radians', async () => { + const surfaces = []; + const shell = createWeatherShell({ + product: 'radar', + viewRectangle: () => ({ west: -1.8, south: 0.5, east: -1.6, north: 0.6 }), + moveEnd: { addEventListener: () => () => {} }, + requestRender: () => {}, + fetchImpl: async () => response(), + decodeImage: async () => ({ + width: 4096, + height: 2048, + close() {}, + }), + createCanvas: canvas, + createSurface: (options) => { + surfaces.push(options); + return { + setAlpha() {}, + setImage() {}, + setWindow() {}, + setDetail() {}, + setHidden() {}, + destroy() {}, + }; + }, + }); + shell.setFrame(snapshot('radar'), '2026-11-04T12:00:00Z'); + await flush(); + assert.equal(surfaces.length, 1); + assert.equal(surfaces[0].cesium, undefined); + const { bounds } = snapshot('radar'); + for (const side of ['west', 'south', 'east', 'north']) + assert.equal( + surfaces[0].rectangle[side], + Cesium.Math.toRadians(bounds[side]), + ); + shell.clear(); +});