Skip to content

Commit

Permalink
Merge pull request #2 from geoblocks/basic_cesium_plugin
Browse files Browse the repository at this point in the history
Add plugin-cesium-widget component
  • Loading branch information
gberaudo authored Aug 30, 2024
2 parents c4b09fe + eb47cbe commit 4ef471e
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 104 deletions.
32 changes: 0 additions & 32 deletions src/apps/illumination/defaultConfig.json

This file was deleted.

40 changes: 40 additions & 0 deletions src/apps/illumination/defaultConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import type {IIlluminationConfig} from './ingv-config-illumination.js';

export const defaultConfig: IIlluminationConfig = {
header: {
languages: ['de', 'fr', 'en', 'it'],
title: {
fr: 'Ma super app',
en: 'My super app',
de: 'Meine supper app',
it: 'Mia super app',
},
},
footer: {
contact: '[email protected]',
impressum: {
fr: 'Bla bla FR impressim',
en: 'Bla bla EN impressim',
de: 'Bla bla DE impressim',
it: 'Bla bla IT impressim',
},
},
app: {
cesiumContext: {
layers: {
terrain: 'https://3d.geo.admin.ch/ch.swisstopo.terrain.3d/v1/',
buildings:
'https://vectortiles0.geo.admin.ch/3d-tiles/ch.swisstopo.swisstlm3d.3d/20201020/tileset.json',
vegetation:
'https://vectortiles.geo.admin.ch/3d-tiles/ch.swisstopo.vegetation.3d/20190313/tileset.json',
},
initialView: {
destination: [6.628484, 46.5, 1000],
orientation: {
heading: 0,
pitch: -30.0,
},
},
},
},
};
5 changes: 1 addition & 4 deletions src/apps/illumination/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,14 @@ import '../../structure/ngv-structure-app.js';
import {localized} from '@lit/localize';
import {ABaseApp} from '../../structure/BaseApp.js';

// @ts-expect-error viteJS specific import
import configUrl from './defaultConfig.json?url';

import './ngv-main-illumination.js';
import {IIlluminationConfig} from './ingv-config-illumination.js';

@customElement('ngv-app-illumination')
@localized()
export class NgvAppIllumination extends ABaseApp<IIlluminationConfig> {
constructor() {
super(configUrl as string);
super(() => import('./defaultConfig.js'));
}

render() {
Expand Down
12 changes: 2 additions & 10 deletions src/apps/illumination/ingv-config-illumination.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
import {IngvCesiumContext} from 'src/interfaces/ingv-cesium-context.js';
import {INgvStructureApp} from '../../structure/ngv-structure-app.js';

export interface IIlluminationConfig extends INgvStructureApp {
app: {
terrain: string;
buildings: string;
vegetation: string;
initialView: {
destination: [number, number, number];
orientation: {
heading: number;
pitch: number;
};
};
cesiumContext: IngvCesiumContext;
};
}
66 changes: 13 additions & 53 deletions src/apps/illumination/ngv-main-illumination.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
import {customElement, property, query, state} from 'lit/decorators.js';
import {css, html, LitElement, PropertyValues} from 'lit';
import {
Cartesian3,
Cesium3DTileset,
CesiumTerrainProvider,
CesiumWidget,
JulianDate,
Math as CMath,
ShadowMode,
Terrain,
} from '@cesium/engine';
import {css, html, LitElement} from 'lit';
import {type CesiumWidget, JulianDate} from '@cesium/engine';
import {IIlluminationConfig} from './ingv-config-illumination.js';

import '../../plugins/ngv-plugin-cesium-widget.js';

const YEAR = new Date().getFullYear();
const BASE_DATE = new Date(`${YEAR}-01-01T00:00:00`);
const BASE_JULIAN_DATE = JulianDate.fromDate(BASE_DATE);
Expand All @@ -22,7 +15,9 @@ export class NgvMainIllumination extends LitElement {
day: number = 1;
@state()
hour: number = 12;

private viewer: CesiumWidget;

@query('#cesium-container')
cesiumContainer: HTMLDivElement;
@query('.hour-slider')
Expand Down Expand Up @@ -121,47 +116,6 @@ export class NgvMainIllumination extends LitElement {
}
`;

private async initializeViewer() {
window.CESIUM_BASE_URL = '/';
const {
terrain: terrainUrl,
buildings: buildingsUrl,
vegetation: vegetationUrl,
initialView,
} = this.config;
this.viewer = new CesiumWidget(this.cesiumContainer, {
shadows: true,
scene3DOnly: true,
terrain: new Terrain(CesiumTerrainProvider.fromUrl(terrainUrl)),
terrainShadows: ShadowMode.ENABLED,
});
const buildingsTS = await Cesium3DTileset.fromUrl(buildingsUrl, {
show: true,
backFaceCulling: false,
});
this.viewer.scene.primitives.add(buildingsTS);
const vegetationTS = await Cesium3DTileset.fromUrl(vegetationUrl, {
show: true,
backFaceCulling: false,
});
this.viewer.scene.primitives.add(vegetationTS);

this.viewer.camera.flyTo({
destination: Cartesian3.fromDegrees(...initialView.destination),
orientation: {
heading: CMath.toRadians(initialView.orientation.heading),
pitch: CMath.toRadians(initialView.orientation.pitch),
},
duration: 0,
});
}

protected async firstUpdated(_changedProperties: PropertyValues) {
await this.initializeViewer();
this.updateDayAndHour();
super.firstUpdated(_changedProperties);
}

// FIXME: extract slider to own component

// FIXME: extract Cesium to own component
Expand Down Expand Up @@ -196,7 +150,13 @@ export class NgvMainIllumination extends LitElement {
/>
</div>
</div>
<div id="cesium-container"></div>
<ngv-plugin-cesium-widget
.config=${this.config.cesiumContext}
@viewerInitialized=${(evt: CustomEvent<CesiumWidget>) => {
this.viewer = evt.detail;
this.updateDayAndHour();
}}
></ngv-plugin-cesium-widget>
</div>
`;
}
Expand Down
16 changes: 16 additions & 0 deletions src/interfaces/ingv-cesium-context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export interface IngvCesiumContext {
cesiumApiKey?: string;
baseUrl?: string;
layers: {
terrain: string;
buildings: string;
vegetation: string;
};
initialView: {
destination: [number, number, number];
orientation: {
heading: number;
pitch: number;
};
};
}
117 changes: 117 additions & 0 deletions src/plugins/ngv-plugin-cesium-widget.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import {LitElement, css, unsafeCSS, html} from 'lit';
import {customElement, property, query} from 'lit/decorators.js';

import {
Ion,
Math as CesiumMath,
CesiumWidget,
Cartesian3,
CesiumTerrainProvider,
Terrain,
ShadowMode,
Cesium3DTileset,
} from '@cesium/engine';

// @ts-expect-error Vite specific ?inline parameter
import style from '@cesium/engine/Source/Widget/CesiumWidget.css?inline';
import {IngvCesiumContext} from 'src/interfaces/ingv-cesium-context.js';

/**
* FIXME: this is really specific:
* - it has a not very flexible set of layers;
* - there is no concept of a catalog / identifier
* - it hardcodes dependency on various types: terrain, 3dtiles, ... (maybe fine?)
* - it forces shadows, backfaceculling, ...
*/
async function initCesium(
container: HTMLDivElement,
config: IngvCesiumContext,
): Promise<CesiumWidget> {
window.CESIUM_BASE_URL = config.baseUrl || '/';

if (config.cesiumApiKey) {
Ion.defaultAccessToken = config.cesiumApiKey;
}

window.CESIUM_BASE_URL = '/';
const {
terrain: terrainUrl,
buildings: buildingsUrl,
vegetation: vegetationUrl,
} = config.layers;
const initialView = config.initialView;

const viewer = new CesiumWidget(container, {
shadows: true,
scene3DOnly: true,
terrain: new Terrain(CesiumTerrainProvider.fromUrl(terrainUrl)),
terrainShadows: ShadowMode.ENABLED,
});
const scene = viewer.scene;
const buildingsTS = await Cesium3DTileset.fromUrl(buildingsUrl, {
show: true,
backFaceCulling: false,
});
scene.primitives.add(buildingsTS);
const vegetationTS = await Cesium3DTileset.fromUrl(vegetationUrl, {
show: true,
backFaceCulling: false,
});
scene.primitives.add(vegetationTS);

viewer.camera.flyTo({
destination: Cartesian3.fromDegrees(...initialView.destination),
orientation: {
heading: CesiumMath.toRadians(initialView.orientation.heading),
pitch: CesiumMath.toRadians(initialView.orientation.pitch),
},
duration: 0,
});

return viewer;
}

@customElement('ngv-plugin-cesium-widget')
export class NgvPluginCesiumWidget extends LitElement {
public viewer: CesiumWidget;

static styles = css`
${unsafeCSS(style)}
:host {
width: 100%;
height: 100%;
display: block;
}
.cesium-credit-logoContainer {
display: none !important;
}
`;

@property({type: Object})
config: IngvCesiumContext;

// The configuration should provide a catalog
@query('#globe')
private element: HTMLDivElement;

protected async firstUpdated(): Promise<void> {
this.viewer = await initCesium(this.element, this.config);
}

render() {
return html`<div id="globe"></div>`;
}
}

declare global {
interface HTMLElementTagNameMap {
'ngv-plugin-cesium-widget': NgvPluginCesiumWidget;
}
}

declare global {
interface Window {
CESIUM_BASE_URL: string;
}
}
18 changes: 14 additions & 4 deletions src/structure/BaseApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,29 @@ export abstract class ABaseApp<ConfigType> extends LitElement {
}
}

private async initializeConfig(configUrl: string) {
private async initializeConfig(
configUrl: string | (() => Promise<{defaultConfig: ConfigType}>),
) {
this.configLoading = 'loading';
try {
const result = await fetch(configUrl);
this.config = (await result.json()) as ConfigType;
if (typeof configUrl === 'function') {
const {defaultConfig} = await configUrl();
this.config = defaultConfig;
} else {
const result = await fetch(configUrl);
this.config = (await result.json()) as ConfigType;
}

this.configLoading = 'ready';
} catch (e) {
this.configLoading = 'error';
console.error(e);
}
}

constructor(configUrl: string) {
constructor(
configUrl: string | (() => Promise<{defaultConfig: ConfigType}>),
) {
super();
try {
this.initializeLocale().catch(() => {});
Expand Down
2 changes: 1 addition & 1 deletion src/structure/ngv-structure-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {getLocale, Locale, setLocale} from './helpers/localeHelper.js';

export interface INgvStructureApp {
header: {
logo: string;
logo?: string;
languages: Locale[];
title: Record<Locale, string>;
};
Expand Down

0 comments on commit 4ef471e

Please sign in to comment.