mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
feat(outlines): restore voice outlines without public Overpass
use bundled place boundaries and shared OpenFreeMap tiles before a guarded Nominatim fallback preserve multipart shapes, holes and cancellation, and keep pending annotations visible while ground sampling finishes across frames keep non-Latin name distinctions when selecting provider results, and retain an outline anchor only when it lies in filled geometry
This commit is contained in:
commit
d4434aa6d7
1489 files changed
+196442
-12353
No files matched your search
@@ -1,11 +1,13 @@
|
||||
import { createStandaloneCatalog } from './catalog.js';
|
||||
import { createStandalonePlaceSearch } from './placeSearch.js';
|
||||
import { CITY_POIS } from '../locations.js';
|
||||
import { CITY_POIS } from '../cityPois.js';
|
||||
import { createApplication } from '../app/application.js';
|
||||
import { createStandaloneScene } from './scene.js';
|
||||
import { createStandaloneControls } from './controls.js';
|
||||
import { createStandaloneData } from './data.js';
|
||||
import { createStandaloneTools } from './tools.js';
|
||||
import { resolveLocale, applyDocumentLanguage } from '../i18n/locale.js';
|
||||
import { applyDocumentTranslations, setLocale } from '../i18n/index.js';
|
||||
|
||||
// The existing controls and layer catalog contain page-scoped state.
|
||||
let constructed = false;
|
||||
@@ -16,11 +18,21 @@ export function createStandaloneApplication({
|
||||
cesiumToken,
|
||||
geospatial = {},
|
||||
voice = {},
|
||||
sources = {},
|
||||
streetLevelProviders,
|
||||
allowQaRegistration = false,
|
||||
}) {
|
||||
if (constructed)
|
||||
throw new Error('The standalone application already owns this page');
|
||||
constructed = true;
|
||||
// Locale is resolved before any UI initialization so <html lang>/<html dir>
|
||||
// and every catalog lookup agree from the first painted frame. Module
|
||||
// scripts execute after parsing, so the DOM is ready here and every
|
||||
// data-i18n* element honors the resolved locale without a reload.
|
||||
const activeLocale = resolveLocale();
|
||||
setLocale(activeLocale);
|
||||
applyDocumentLanguage(document, activeLocale);
|
||||
applyDocumentTranslations(document);
|
||||
const loadingScreen = document.getElementById('loading-screen');
|
||||
const loaderStatus = loadingScreen.querySelector('.loader-status');
|
||||
let placeSearch;
|
||||
@@ -43,6 +55,8 @@ export function createStandaloneApplication({
|
||||
loaderStatus,
|
||||
});
|
||||
catalog = createStandaloneCatalog({
|
||||
sources,
|
||||
streetLevelProviders,
|
||||
nepalBoundaryResolver: (signal) =>
|
||||
scene.operations.annotationResolver.resolveRegionRingForQuery(
|
||||
'Nepal',
|
||||
|
||||
@@ -7,6 +7,8 @@ export { createStandaloneReferenceSources } from './layerSources.js';
|
||||
/** Create fresh layer instances using the existing standalone source choices. */
|
||||
export function createStandaloneCatalog({
|
||||
nepalBoundaryResolver,
|
||||
sources = {},
|
||||
streetLevelProviders,
|
||||
signal = new AbortController().signal,
|
||||
surface = createSurfaceServices({
|
||||
terrainSource: createApplicationRequestServices().terrain,
|
||||
@@ -16,7 +18,8 @@ export function createStandaloneCatalog({
|
||||
return createApplicationCatalog({
|
||||
nepalBoundaryResolver,
|
||||
surface,
|
||||
sources: createStandaloneLayerSources(),
|
||||
sources: createStandaloneLayerSources(sources),
|
||||
streetLevelProviders,
|
||||
signal,
|
||||
vesselOptions: {
|
||||
maxRows: import.meta.env?.VITE_AIS_LIVE_MAX_ROWS,
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { createDirectionsSource } from '../layers/directions/source.js';
|
||||
import { createRecentImagerySource } from '../layers/recentImagery/source.js';
|
||||
import { createOpenFreeMapSource } from '../sources/openFreeMap.js';
|
||||
import {
|
||||
createOpenSkySource,
|
||||
createAdsbLolSource,
|
||||
createAisStreamSource,
|
||||
createFlightSource,
|
||||
createMilitarySource,
|
||||
createVesselSource,
|
||||
} from '../sources/live/standalone.js';
|
||||
import { createCctvSource } from '../layers/cctv/source.js';
|
||||
import { createRadioSource } from '../layers/radio/source.js';
|
||||
@@ -17,23 +19,32 @@ import { createWeatherSource } from '../layers/weather/source.js';
|
||||
import { createCycloneSource } from '../layers/cyclones/source.js';
|
||||
import { createWindSource } from '../layers/wind/source.js';
|
||||
import { createFirmsSource } from '../layers/firms/source.js';
|
||||
import { createGhostMapsSource } from '../layers/ghostMaps/source.js';
|
||||
import { createMapillarySource } from '../layers/streetLevel/providers/mapillary/source.js';
|
||||
import { createReferenceSources } from '../sources/reference.js';
|
||||
export { createReferenceSources as createStandaloneReferenceSources } from '../sources/reference.js';
|
||||
|
||||
/** Select standalone providers without starting their acquisition. */
|
||||
export function createStandaloneLayerSources({
|
||||
createMapTiles = createOpenFreeMapSource,
|
||||
} = {}) {
|
||||
// Each subsystem owns its own request lifetime and local result cache. The
|
||||
// sources still share the bounded decoded-tile owner inside OpenFreeMap.
|
||||
const trafficTiles = createMapTiles();
|
||||
const installationTiles = createMapTiles();
|
||||
return {
|
||||
export function createStandaloneLayerSources(
|
||||
overrides = {},
|
||||
{ createMapTiles = createOpenFreeMapSource } = {},
|
||||
) {
|
||||
if (!overrides || typeof overrides !== 'object' || Array.isArray(overrides))
|
||||
throw new TypeError('Source overrides must be an object');
|
||||
const trafficTiles = createMapTiles({
|
||||
selectDecoded: ({ roads }) => ({ roads }),
|
||||
});
|
||||
const installationTiles = createMapTiles({
|
||||
selectDecoded: ({ military }) => ({ military }),
|
||||
});
|
||||
const defaults = {
|
||||
...createReferenceSources(),
|
||||
flights: createOpenSkySource(),
|
||||
military: createAdsbLolSource(),
|
||||
vessels: createAisStreamSource({
|
||||
apiUrl: import.meta.env?.VITE_AIS_LIVE_API_URL || '/api/ais-live',
|
||||
directions: createDirectionsSource(),
|
||||
'recent-imagery': createRecentImagerySource(),
|
||||
flights: createFlightSource(),
|
||||
military: createMilitarySource(),
|
||||
vessels: createVesselSource({
|
||||
apiUrl: import.meta.env?.VITE_AIS_LIVE_API_URL || '/api/vessels',
|
||||
// Resolved against the document's address, which a panel host may
|
||||
// serve from its own scheme.
|
||||
origin: () => globalThis.document?.baseURI ?? 'http://localhost',
|
||||
@@ -48,8 +59,17 @@ export function createStandaloneLayerSources({
|
||||
launches: createLaunchSource(),
|
||||
alpr: createAlprTileSource(),
|
||||
firms: createFirmsSource(),
|
||||
's2-ghostmaps': createGhostMapsSource(),
|
||||
wind: createWindSource(),
|
||||
weather: createWeatherSource(),
|
||||
cyclones: createCycloneSource(),
|
||||
mapillary: createMapillarySource({
|
||||
token: import.meta.env?.MAPILLARY_CLIENT_TOKEN || '',
|
||||
}),
|
||||
};
|
||||
for (const name of Object.keys(overrides)) {
|
||||
if (!Object.hasOwn(defaults, name))
|
||||
throw new TypeError(`Unknown source: ${name}`);
|
||||
}
|
||||
return { ...defaults, ...overrides };
|
||||
}
|
||||
@@ -4,25 +4,38 @@ import { createStandaloneLayerSources } from './layerSources.js';
|
||||
|
||||
test('traffic and installations own separate local OpenFreeMap lifetimes', () => {
|
||||
const mapTiles = [];
|
||||
const sources = createStandaloneLayerSources({
|
||||
createMapTiles() {
|
||||
const source = {
|
||||
clears: 0,
|
||||
clear() {
|
||||
this.clears++;
|
||||
},
|
||||
getMetadata: async () => ({
|
||||
template: 'https://tiles.openfreemap.org/planet/test/{z}/{x}/{y}.pbf',
|
||||
}),
|
||||
fetchBounds: async () => ({ tiles: [], loadedTiles: [] }),
|
||||
};
|
||||
mapTiles.push(source);
|
||||
return source;
|
||||
const mapTileOptions = [];
|
||||
const sources = createStandaloneLayerSources(
|
||||
{},
|
||||
{
|
||||
createMapTiles(options) {
|
||||
mapTileOptions.push(options);
|
||||
const source = {
|
||||
clears: 0,
|
||||
clear() {
|
||||
this.clears++;
|
||||
},
|
||||
getMetadata: async () => ({
|
||||
template:
|
||||
'https://tiles.openfreemap.org/planet/test/{z}/{x}/{y}.pbf',
|
||||
}),
|
||||
fetchBounds: async () => ({ tiles: [], loadedTiles: [] }),
|
||||
};
|
||||
mapTiles.push(source);
|
||||
return source;
|
||||
},
|
||||
},
|
||||
});
|
||||
);
|
||||
|
||||
assert.equal(mapTiles.length, 2);
|
||||
assert.notEqual(mapTiles[0], mapTiles[1]);
|
||||
const decoded = { roads: ['road'], military: ['site'] };
|
||||
assert.deepEqual(mapTileOptions[0].selectDecoded(decoded), {
|
||||
roads: ['road'],
|
||||
});
|
||||
assert.deepEqual(mapTileOptions[1].selectDecoded(decoded), {
|
||||
military: ['site'],
|
||||
});
|
||||
sources.traffic.resetFlowTileCache();
|
||||
assert.deepEqual(
|
||||
mapTiles.map((source) => source.clears),
|
||||
|
||||
@@ -17,6 +17,11 @@ export function createStandaloneTools(options) {
|
||||
},
|
||||
},
|
||||
...options,
|
||||
voice: { toolCatalog: loadToolCatalog, ...options?.voice },
|
||||
voice: {
|
||||
supportedProviders: ['openai', 'gemini'],
|
||||
panel: true,
|
||||
toolCatalog: loadToolCatalog,
|
||||
...options?.voice,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export { StyleManager } from '../ui/composition.js';
|
||||
Reference in new issue
Block a user