diff --git a/src/apps/permits/demoPermitConfig.ts b/src/apps/permits/demoPermitConfig.ts index 5132a02..da28ff0 100644 --- a/src/apps/permits/demoPermitConfig.ts +++ b/src/apps/permits/demoPermitConfig.ts @@ -28,10 +28,13 @@ export const config: IPermitsConfig = { }, layers: { tiles3d: ['@geoadmin/buildings'], // @cesium/googlePhotorealistic - // models: ['@demo/sofa', '@demo/thatopensmall'], + models: ['@demo/sofa', '@demo/thatopensmall'], imageries: ['@geoadmin/pixel-karte-farbe'], terrain: '@geoadmin/terrain', }, + quickLists: { + baseLayers: ['@geoadmin/pixel-karte-farbe'], + }, camera: { position: [6.628484, 46.5, 1000], orientation: { @@ -39,6 +42,34 @@ export const config: IPermitsConfig = { pitch: -30.0, }, }, + views: [ + { + positions: [ + [6.62571, 46.50666], + [6.62582, 46.50659], + [6.62556, 46.50655], + [6.62566, 46.50648], + ], + height: 5, + elevation: 374, + flyDuration: 2, + title: 'Building', + fovAngle: 45, + }, + { + positions: [ + [6.62582, 46.50651], + [6.62587, 46.50654], + [6.62592, 46.50651], + [6.62587, 46.50648], + ], + height: 2, + elevation: 374, + flyDuration: 2, + title: 'Building 2', + fovAngle: 45, + }, + ], layerOptions: {}, widgetOptions: { scene3DOnly: true, diff --git a/src/apps/permits/index.ts b/src/apps/permits/index.ts index f7861ef..b95d11d 100644 --- a/src/apps/permits/index.ts +++ b/src/apps/permits/index.ts @@ -15,6 +15,7 @@ import '../../plugins/cesium/ngv-plugin-cesium-upload'; import '../../plugins/cesium/ngv-plugin-cesium-model-interact'; import '../../plugins/cesium/ngv-plugin-cesium-slicing'; import '../../plugins/cesium/ngv-plugin-cesium-measure'; +import '../../plugins/cesium/ngv-plugin-cesium-navigation'; import type {CesiumWidget, DataSourceCollection} from '@cesium/engine'; import {PrimitiveCollection} from '@cesium/engine'; @@ -34,6 +35,8 @@ export class NgvAppPermits extends ABaseApp { indexDbName: 'permits-uploadedModelsStore', }; + private sliceStoreKey = 'permits-localStoreClipping'; + private collections: ViewerInitializedDetails['primitiveCollections']; constructor() { @@ -80,11 +83,18 @@ export class NgvAppPermits extends ABaseApp { .viewer="${this.viewer}" .tiles3dCollection="${this.collections.tiles3d}" .dataSourceCollection="${this.dataSourceCollection}" + .storeKey="${this.sliceStoreKey}" > + ` : ''} diff --git a/src/catalogs/demoCatalog.ts b/src/catalogs/demoCatalog.ts index 9645de3..738e230 100644 --- a/src/catalogs/demoCatalog.ts +++ b/src/catalogs/demoCatalog.ts @@ -12,9 +12,10 @@ export const catalog: INGVCatalog = { credit: 'test', }, }, - position: [6.628484, 46.5], - height: 0, - rotation: 0, + position: [6.625727097014207, 46.50662035273721], + // todo apply terrain height automatically? + height: 374, + rotation: 45, }, sofa: { type: 'model', @@ -22,9 +23,10 @@ export const catalog: INGVCatalog = { url: 'https://raw.GithubUserContent.com/KhronosGroup/glTF-Sample-Assets/main/./Models/SheenWoodLeatherSofa/glTF-Binary/SheenWoodLeatherSofa.glb', credit: 'Khonos', }, - position: [6.628484, 46.5], - height: 0, - rotation: 0, + position: [6.625858407650085, 46.50649671101955], + // todo apply terrain height automatically? + height: 374, + rotation: 239, }, // to complete }, diff --git a/src/interfaces/cesium/ingv-cesium-context.ts b/src/interfaces/cesium/ingv-cesium-context.ts index bf6089c..524b9df 100644 --- a/src/interfaces/cesium/ingv-cesium-context.ts +++ b/src/interfaces/cesium/ingv-cesium-context.ts @@ -31,6 +31,30 @@ export interface IngvCesiumContext { pitch: number; }; }; + views?: { + positions: [ + [number, number], + [number, number], + [number, number], + [number, number], + ]; + height: number; + elevation: number; + title: string; + flyDuration?: number; + fovAngle: number; + highlightColor?: string; // css string, default red + }[]; widgetOptions?: ConstructorParameters[1]; globeOptions?: Partial; + measureOptions?: { + areaFill?: string; + lineColor?: string; + lineWidth?: number; + showPoints?: boolean; + pointColor?: string; + pointOutlineWidth?: number; + pointOutlineColor?: string; + pointPixelSize?: number; + }; } diff --git a/src/plugins/cesium/draw.ts b/src/plugins/cesium/draw.ts index 1099617..2a5e2be 100644 --- a/src/plugins/cesium/draw.ts +++ b/src/plugins/cesium/draw.ts @@ -42,7 +42,14 @@ export interface DrawOptions { strokeColor?: string | Color; strokeWidth?: number; minPointsStop?: boolean; - pointOptions?: PointOptions; + pointOptions?: Omit< + PointOptions, + 'color' | 'virtualColor' | 'outlineColor' + > & { + color?: Color | string; + virtualColor?: Color | string; + outlineColor?: Color | string; + }; lineClampToGround?: boolean; } @@ -129,15 +136,17 @@ export class CesiumDraw extends EventTarget { const heightReference = pointOptions?.heightReference; this.pointOptions = { color: - pointOptions?.color instanceof Color ? pointOptions.color : Color.WHITE, + pointOptions?.color instanceof Color + ? pointOptions.color + : Color.fromCssColorString(pointOptions?.color || '#fff'), virtualColor: pointOptions?.virtualColor instanceof Color ? pointOptions.virtualColor - : Color.GREY, + : Color.fromCssColorString(pointOptions?.virtualColor || '#808080'), outlineColor: pointOptions?.outlineColor instanceof Color ? pointOptions.outlineColor - : Color.BLACK, + : Color.fromCssColorString(pointOptions?.outlineColor || '#000'), outlineWidth: typeof pointOptions?.outlineWidth === 'number' && !isNaN(pointOptions?.outlineWidth) diff --git a/src/plugins/cesium/interactionHelpers.ts b/src/plugins/cesium/interactionHelpers.ts index 0452edb..3266dd5 100644 --- a/src/plugins/cesium/interactionHelpers.ts +++ b/src/plugins/cesium/interactionHelpers.ts @@ -1,11 +1,13 @@ import type { Cesium3DTileset, CustomDataSource, + DirectionUp, Globe, Model, PrimitiveCollection, Scene, } from '@cesium/engine'; +import {Math as CMath} from '@cesium/engine'; import {ClippingPolygonCollection} from '@cesium/engine'; import { ArcType, @@ -638,3 +640,68 @@ export function updateHeightForCartesianPositions( : Cartographic.toCartesian(cartographicPosition); }); } + +export function calculateViewOnRectangle( + bottomLeft: Cartesian3, + bottomRight: Cartesian3, + topLeft: Cartesian3, + topRight: Cartesian3, + fovAngle: number, +): { + destination: Cartesian3; + orientation: DirectionUp; +} { + // Calculate the midpoint of the rectangle + const midpoint = Cartesian3.multiplyByScalar( + Cartesian3.add( + Cartesian3.add(bottomLeft, bottomRight, new Cartesian3()), + Cartesian3.add(topLeft, topRight, new Cartesian3()), + new Cartesian3(), + ), + 0.25, + new Cartesian3(), + ); + + const verticalDistance = Cartesian3.distance(topLeft, bottomLeft); + const horizontalDistance = Cartesian3.distance(bottomLeft, bottomRight); + const diagonalDistance = Math.sqrt( + verticalDistance ** 2 + horizontalDistance ** 2, + ); + + const fov = CMath.toRadians(fovAngle); + const cameraDistance = diagonalDistance / (2 * Math.tan(fov / 2)); + + // Calculate the normal vector of the rectangle plane + const horizontalVector = Cartesian3.subtract( + bottomRight, + bottomLeft, + new Cartesian3(), + ); + const verticalVector = Cartesian3.subtract( + topLeft, + bottomLeft, + new Cartesian3(), + ); + + const normalVector = Cartesian3.normalize( + Cartesian3.cross(horizontalVector, verticalVector, new Cartesian3()), + new Cartesian3(), + ); + + // Camera position is offset along the normal vector + const cameraPosition = Cartesian3.add( + midpoint, + Cartesian3.multiplyByScalar(normalVector, cameraDistance, new Cartesian3()), + new Cartesian3(), + ); + + const cameraDirection = Cartesian3.negate(normalVector, new Cartesian3()); + + return { + destination: cameraPosition, + orientation: { + direction: cameraDirection, + up: verticalVector, + }, + }; +} diff --git a/src/plugins/cesium/localStore.ts b/src/plugins/cesium/localStore.ts index e0d2934..d21e332 100644 --- a/src/plugins/cesium/localStore.ts +++ b/src/plugins/cesium/localStore.ts @@ -162,16 +162,17 @@ export type StoredClipping = { tilesClipping: boolean; }; -const CLIPPING_KEY = 'clipping-polygons'; - -export function updateClippingInLocalStore(clipping: StoredClipping[]): void { - localStorage.setItem(CLIPPING_KEY, JSON.stringify(clipping)); +export function updateClippingInLocalStore( + clipping: StoredClipping[], + key: string, +): void { + localStorage.setItem(key, JSON.stringify(clipping)); } -export function getStoredClipping(): StoredClipping[] { - if (!localStorage.getItem(CLIPPING_KEY)) return []; +export function getStoredClipping(key: string): StoredClipping[] { + if (!localStorage.getItem(key)) return []; try { - return JSON.parse(localStorage.getItem(CLIPPING_KEY)); + return JSON.parse(localStorage.getItem(key)); } catch (e) { console.error('Not possible to parse clippings from local storage', e); return []; diff --git a/src/plugins/cesium/ngv-cesium-factories.ts b/src/plugins/cesium/ngv-cesium-factories.ts index 09e57f3..4529a5f 100644 --- a/src/plugins/cesium/ngv-cesium-factories.ts +++ b/src/plugins/cesium/ngv-cesium-factories.ts @@ -267,7 +267,7 @@ export async function initCesiumWidget( const viewer = new CesiumWidget( container, - Object.assign({}, cesiumContext.widgetOptions), + Object.assign({baseLayer: false}, cesiumContext.widgetOptions), ); if (cesiumContext.globeOptions) { diff --git a/src/plugins/cesium/ngv-plugin-cesium-measure.ts b/src/plugins/cesium/ngv-plugin-cesium-measure.ts index efe0f7c..f1060df 100644 --- a/src/plugins/cesium/ngv-plugin-cesium-measure.ts +++ b/src/plugins/cesium/ngv-plugin-cesium-measure.ts @@ -5,6 +5,18 @@ import type {CesiumWidget, DataSourceCollection, Entity} from '@cesium/engine'; import {Color, CustomDataSource, HeightReference} from '@cesium/engine'; import type {DrawInfo} from './draw.js'; import {CesiumDraw, type DrawEndDetails, getDimensionLabel} from './draw.js'; +import type {IngvCesiumContext} from '../../interfaces/cesium/ingv-cesium-context.js'; + +const DefaultConfig: IngvCesiumContext['measureOptions'] = { + areaFill: 'rgba(0, 153, 255, 0.3)', + lineColor: 'rgba(0, 153, 255, 0.75)', + lineWidth: 4, + showPoints: true, + pointColor: '#fff', + pointOutlineWidth: 1, + pointOutlineColor: '#000', + pointPixelSize: 5, +}; @customElement('ngv-plugin-cesium-measure') export class NgvPluginCesiumMeasure extends LitElement { @@ -12,6 +24,8 @@ export class NgvPluginCesiumMeasure extends LitElement { private viewer: CesiumWidget; @property({type: Object}) private dataSourceCollection: DataSourceCollection; + @property({type: Object}) + private options: IngvCesiumContext['measureOptions']; @state() private measurements: Partial; private draw: CesiumDraw; @@ -62,8 +76,21 @@ export class NgvPluginCesiumMeasure extends LitElement { .then((drawDataSource) => { this.draw = new CesiumDraw(this.viewer, drawDataSource, { lineClampToGround: false, + strokeColor: this.options?.lineColor || DefaultConfig.lineColor, + fillColor: this.options?.areaFill || DefaultConfig.areaFill, + strokeWidth: this.options?.lineWidth || DefaultConfig.lineWidth, pointOptions: { heightReference: HeightReference.NONE, + color: this.options?.pointColor || DefaultConfig.pointColor, + outlineColor: + this.options?.pointOutlineColor || + DefaultConfig.pointOutlineColor, + outlineWidth: + typeof this.options?.pointOutlineWidth === 'number' + ? this.options?.pointOutlineWidth + : DefaultConfig.pointOutlineWidth, + pixelSizeDefault: + this.options?.pointPixelSize || DefaultConfig.pointPixelSize, }, }); this.draw.addEventListener('drawend', (e) => { @@ -72,39 +99,68 @@ export class NgvPluginCesiumMeasure extends LitElement { this.measureDataSource.entities.add({ polyline: { positions: details.positions, - material: Color.RED, - width: 4, + material: Color.fromCssColorString( + this.options?.lineColor || DefaultConfig.lineColor, + ), + width: this.options?.lineWidth || DefaultConfig.lineWidth, }, }); } else { this.measureDataSource.entities.add({ polygon: { hierarchy: details.positions, - material: Color.YELLOW.withAlpha(0.7), + material: Color.fromCssColorString( + this.options?.lineColor || DefaultConfig.lineColor, + ), perPositionHeight: true, }, }); } - details.positions.forEach((p, index) => { - const entity: Entity.ConstructorOptions = { - position: p, - point: { - color: Color.WHITE, - outlineWidth: 1, - outlineColor: Color.BLACK, - pixelSize: 5, - heightReference: HeightReference.NONE, - }, - }; - if (index === details.positions.length - 1) { - entity.label = getDimensionLabel({ + if ( + (typeof this.options?.showPoints === 'boolean' && + this.options.showPoints) || + DefaultConfig.showPoints + ) { + details.positions.forEach((p, index) => { + const entity: Entity.ConstructorOptions = { + position: p, + point: { + color: Color.fromCssColorString( + this.options?.pointColor || DefaultConfig.pointColor, + ), + outlineWidth: + typeof this.options?.pointOutlineWidth === 'number' + ? this.options?.pointOutlineWidth + : DefaultConfig.pointOutlineWidth, + outlineColor: Color.fromCssColorString( + this.options?.pointOutlineColor || + DefaultConfig.pointOutlineColor, + ), + pixelSize: + this.options?.pointPixelSize || + DefaultConfig.pointPixelSize, + heightReference: HeightReference.NONE, + }, + }; + if (index === details.positions.length - 1) { + entity.label = getDimensionLabel({ + type: details.type, + positions: details.positions, + distances: details.measurements.segmentsLength, + }); + } + this.measureDataSource.entities.add(entity); + }); + } else { + this.measureDataSource.entities.add({ + position: details.positions[details.positions.length - 1], + label: getDimensionLabel({ type: details.type, positions: details.positions, distances: details.measurements.segmentsLength, - }); - } - this.measureDataSource.entities.add(entity); - }); + }), + }); + } this.draw.active = false; }); this.draw.addEventListener('drawinfo', (e) => { diff --git a/src/plugins/cesium/ngv-plugin-cesium-model-interact.ts b/src/plugins/cesium/ngv-plugin-cesium-model-interact.ts index d48f0bc..eb1c7ab 100644 --- a/src/plugins/cesium/ngv-plugin-cesium-model-interact.ts +++ b/src/plugins/cesium/ngv-plugin-cesium-model-interact.ts @@ -10,6 +10,8 @@ import type { Cesium3DTileset, Event, } from '@cesium/engine'; +import {Matrix3, HeadingPitchRoll} from '@cesium/engine'; +import {Cartographic, Math as CMath} from '@cesium/engine'; import { Model, Cartesian3, @@ -311,7 +313,12 @@ export class NgvPluginCesiumModelInteract extends LitElement { const obj: {id: Entity | undefined; primitive: Model | undefined} = < {id: Entity | undefined; primitive: Model | undefined} >this.viewer.scene.pick(position); - if (!obj) return; + if (!obj) { + if (this.cursor !== 'default') { + this.viewer.canvas.style.cursor = this.cursor = 'default'; + } + return; + } const pickedEntity = this.chosenModel && obj?.id && obj.id instanceof Entity @@ -323,7 +330,12 @@ export class NgvPluginCesiumModelInteract extends LitElement { this.primitiveCollection.contains(obj.primitive) ? obj.primitive : undefined; - if (!pickedEntity && !model) return; + if (!pickedEntity && !model) { + if (this.cursor !== 'default') { + this.viewer.canvas.style.cursor = this.cursor = 'default'; + } + return; + } const isEdge = pickedEntity && this.edgeLinesDataSource.entities.contains(pickedEntity); @@ -501,6 +513,28 @@ export class NgvPluginCesiumModelInteract extends LitElement { ); }} @done="${() => { + const modelMatrix = this.chosenModel.modelMatrix; + const cartesianPosition = new Cartesian3(); + Matrix4.getTranslation(modelMatrix, cartesianPosition); + const cartographicPosition = + Cartographic.fromCartesian(cartesianPosition); + const longitude = CMath.toDegrees(cartographicPosition.longitude); + const latitude = CMath.toDegrees(cartographicPosition.latitude); + const height = cartographicPosition.height; + // todo show in panel + console.log( + `Longitude: ${longitude}, Latitude: ${latitude}, Height: ${height}`, + ); + const rotationMatrix = new Matrix3(); + Matrix4.getRotation(modelMatrix, rotationMatrix); + const euler = HeadingPitchRoll.fromQuaternion( + Quaternion.fromRotationMatrix(rotationMatrix), + ); + const heading = CMath.toDegrees(euler.heading); + const pitch = CMath.toDegrees(euler.pitch); + const roll = CMath.toDegrees(euler.roll); + // todo show in panel + console.log(`Heading: ${heading}, Pitch: ${pitch}, Roll: ${roll}`); this.chosenModel = undefined; this.sidePlanesDataSource.entities.removeAll(); this.topDownPlanesDataSource.entities.removeAll(); diff --git a/src/plugins/cesium/ngv-plugin-cesium-navigation.ts b/src/plugins/cesium/ngv-plugin-cesium-navigation.ts new file mode 100644 index 0000000..0b30ed1 --- /dev/null +++ b/src/plugins/cesium/ngv-plugin-cesium-navigation.ts @@ -0,0 +1,300 @@ +import {customElement, property, state} from 'lit/decorators.js'; +import {css, html, type HTMLTemplateResult, LitElement} from 'lit'; +import {Task} from '@lit/task'; +import type { + CesiumWidget, + DataSourceCollection, + DirectionUp, +} from '@cesium/engine'; +import type {Cartesian3} from '@cesium/engine'; +import { + Cartographic, + Color, + CustomDataSource, + Entity, + HeightReference, + Rectangle, +} from '@cesium/engine'; +import type {IngvCesiumContext} from '../../interfaces/cesium/ingv-cesium-context.js'; +import { + calculateViewOnRectangle, + updateHeightForCartesianPositions, +} from './interactionHelpers.js'; +import {msg} from '@lit/localize'; + +type NavView = { + destination: Cartesian3; + orientation: DirectionUp; + duration?: number; +}; + +type NavViews = { + top: NavView; + north: NavView; + west: NavView; + east: NavView; + south: NavView; + title: string; + highlightEntity: Entity; +}; + +@customElement('ngv-plugin-cesium-navigation') +export class NgvPluginCesiumNavigation extends LitElement { + @property({type: Object}) + public viewer: CesiumWidget; + @property({type: Object}) + public dataSourceCollection: DataSourceCollection; + @property({type: Array}) + public viewsConfig: IngvCesiumContext['views']; + @state() + private tilesToLoad = 0; + @state() + private currentViewIndex: number; + private currentView: NavViews; + private dataSource: CustomDataSource = new CustomDataSource(); + + static styles = css` + button { + border-radius: 4px; + padding: 0 16px; + height: 40px; + cursor: pointer; + background-color: white; + border: 1px solid rgba(0, 0, 0, 0.16); + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.05); + transition: background-color 200ms; + width: 100%; + } + + button[disabled] { + cursor: not-allowed; + } + + .container { + display: flex; + flex-direction: column; + margin-left: auto; + margin-right: auto; + padding: 10px; + gap: 10px; + border-radius: 4px; + border: 1px solid rgba(0, 0, 0, 0.16); + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.05); + } + + .nav-container { + display: flex; + column-gap: 5px; + } + + .view-btns { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + column-gap: 5px; + align-items: center; + } + + .view-btns > div { + display: flex; + flex-direction: column; + row-gap: 5px; + } + + .view-container { + display: flex; + flex-direction: column; + row-gap: 5px; + padding: 5px; + } + + .view-container > h4 { + margin: 0; + padding: 5px; + } + + .view-container > h4:hover { + background-color: lightyellow; + cursor: pointer; + } + + .divider { + width: 100%; + border: 1px solid #e0e3e6; + } + `; + + updateView(): void { + const v = this.viewsConfig[this.currentViewIndex]; + const positions: Cartographic[] = v.positions.map((p) => + Cartographic.fromDegrees(p[0], p[1]), + ); + + const baseRect = Rectangle.fromCartographicArray(positions); + + const nw = Cartographic.toCartesian(Rectangle.northwest(baseRect)); + const ne = Cartographic.toCartesian(Rectangle.northeast(baseRect)); + const sw = Cartographic.toCartesian(Rectangle.southwest(baseRect)); + const se = Cartographic.toCartesian(Rectangle.southeast(baseRect)); + const bottomPositions = [nw, ne, se, sw]; + updateHeightForCartesianPositions(bottomPositions, v.elevation, null, true); + const [nwt, net, set, swt] = updateHeightForCartesianPositions( + bottomPositions, + v.elevation + v.height, + ); + + const highlightEntity = this.dataSource.entities.add( + new Entity({ + show: false, + polygon: { + hierarchy: bottomPositions, + heightReference: HeightReference.RELATIVE_TO_GROUND, + extrudedHeightReference: HeightReference.RELATIVE_TO_GROUND, + material: v.highlightColor + ? Color.fromCssColorString(v.highlightColor) + : Color.RED.withAlpha(0.6), + extrudedHeight: v.height, + }, + }), + ); + + this.currentView = { + top: { + ...calculateViewOnRectangle(swt, set, nwt, net, v.fovAngle), + duration: v.flyDuration, + }, + north: { + ...calculateViewOnRectangle(ne, nw, net, nwt, v.fovAngle), + duration: v.flyDuration, + }, + east: { + ...calculateViewOnRectangle(se, ne, set, net, v.fovAngle), + duration: v.flyDuration, + }, + west: { + ...calculateViewOnRectangle(nw, sw, nwt, swt, v.fovAngle), + duration: v.flyDuration, + }, + south: { + ...calculateViewOnRectangle(sw, se, swt, set, v.fovAngle), + duration: v.flyDuration, + }, + title: v.title, + highlightEntity, + }; + } + + // @ts-expect-error TS6133 + private _changeViewTask = new Task(this, { + args: (): [number] => [this.currentViewIndex], + task: ([_currentViewIndex]) => { + this.updateView(); + this.viewer.camera.flyTo(this.currentView.south); + }, + }); + + firstUpdated(): void { + this.dataSourceCollection + .add(this.dataSource) + .then(() => { + this.currentViewIndex = 0; + this.updateView(); + }) + .catch((err) => console.error(err)); + } + + toNextView(): void { + if (!this.viewsConfig) return; + const nextIndx = this.currentViewIndex + 1; + if (nextIndx >= this.viewsConfig.length) { + this.currentViewIndex = 0; + return; + } + this.currentViewIndex = nextIndx; + } + + toPrevView(): void { + if (!this.viewsConfig) return; + const prevIndx = this.currentViewIndex - 1; + if (prevIndx < 0) { + this.currentViewIndex = this.viewsConfig.length - 1; + return; + } + this.currentViewIndex = prevIndx; + } + + render(): HTMLTemplateResult | string { + return html`
+ ${this.tilesToLoad > 0 + ? msg( + `Please wait for tiles loading. ${this.tilesToLoad} tiles to load`, + ) + : html` + ${this.viewsConfig.length > 1 + ? html` +
` + : ''} + ${!this.currentView + ? '' + : html`
+

+ ${this.currentView.title} +

+
+ +
+ + + +
+ +
+
`} + `} +
`; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'ngv-plugin-cesium-navigation': NgvPluginCesiumNavigation; + } +} diff --git a/src/plugins/cesium/ngv-plugin-cesium-slicing.ts b/src/plugins/cesium/ngv-plugin-cesium-slicing.ts index 3429bf1..e390284 100644 --- a/src/plugins/cesium/ngv-plugin-cesium-slicing.ts +++ b/src/plugins/cesium/ngv-plugin-cesium-slicing.ts @@ -42,6 +42,8 @@ export class NgvPluginCesiumSlicing extends LitElement { private tiles3dCollection: PrimitiveCollection; @property({type: Object}) private dataSourceCollection: DataSourceCollection; + @property({type: String}) + private storeKey: string; @state() private clippingPolygons: ClippingData[] = []; @state() @@ -86,23 +88,26 @@ export class NgvPluginCesiumSlicing extends LitElement { this.dataSourceCollection .add(this.slicingDataSource) .then(() => { - const storedClipping = getStoredClipping(); - storedClipping.forEach((clipping) => { - const positions = clipping.positions.map( - (p) => new Cartesian3(p[0], p[1], p[2]), - ); - const entity = this.drawPolygon(positions, clipping.name, { - terrainClipping: clipping.terrainClipping, - tilesClipping: clipping.tilesClipping, + if (this.storeKey) { + const storedClipping = getStoredClipping(this.storeKey); + storedClipping.forEach((clipping) => { + const positions = clipping.positions.map( + (p) => new Cartesian3(p[0], p[1], p[2]), + ); + if (positions?.length < 3) return; + const entity = this.drawPolygon(positions, clipping.name, { + terrainClipping: clipping.terrainClipping, + tilesClipping: clipping.tilesClipping, + }); + const clippingData = { + entity, + clipping: new ClippingPolygon({positions}), + }; + this.clippingPolygons.push(clippingData); + this.applyClipping(clippingData); }); - const clippingData = { - entity, - clipping: new ClippingPolygon({positions}), - }; - this.clippingPolygons.push(clippingData); - this.applyClipping(clippingData); - }); - this.requestUpdate(); + this.requestUpdate(); + } }) .catch((e) => console.error(e)); this.dataSourceCollection @@ -125,6 +130,7 @@ export class NgvPluginCesiumSlicing extends LitElement { } saveToLocalStore(): void { + if (!this.storeKey) return; const clippingsToStore: StoredClipping[] = this.slicingDataSource.entities.values.map((e) => { const properties = ( @@ -139,7 +145,7 @@ export class NgvPluginCesiumSlicing extends LitElement { tilesClipping: properties.tilesClipping, }; }); - updateClippingInLocalStore(clippingsToStore); + updateClippingInLocalStore(clippingsToStore, this.storeKey); } onDrawEnd(details: DrawEndDetails): void {