Skip to content

Commit

Permalink
Activate Zoom-to-Button for all layers
Browse files Browse the repository at this point in the history
  • Loading branch information
vladyslav-tk committed Jul 16, 2024
1 parent 6313b05 commit 8af06a1
Show file tree
Hide file tree
Showing 10 changed files with 83 additions and 103 deletions.
2 changes: 2 additions & 0 deletions ui/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export const SWITZERLAND_RECTANGLE = Rectangle.fromDegrees(...SWITZERLAND_BOUNDS

export const MINIMAP_EXTENT = [5.910642046, 45.191912227, 10.554524194, 48.04750923];

export const MAP_RECTANGLE = Rectangle.fromDegrees(...[5.91, 45.8179, 10.9, 47.9]);

export const WEB_MERCATOR_TILING_SCHEME = new GeographicTilingScheme({
ellipsoid: Ellipsoid.WGS84,
rectangle: SWITZERLAND_RECTANGLE,
Expand Down
70 changes: 34 additions & 36 deletions ui/src/earthquakeVisualization/earthquakeVisualizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,44 +35,42 @@ export default class EarthquakeVisualizer {
}

async showEarthquakes() {
fetch(this.config.downloadUrl).then(response => {
response.text().then(text => {
parseEarthquakeData(text).map(data => {
const size = Number(data.Magnitude.split(' ')[0]) * EARTHQUAKE_SPHERE_SIZE_COEF;
const depthMeters = Number(data.Depthkm.split(' ')[0]) * 1000; // convert km to m
const longitude = Number(data.Longitude);
const latitude = Number(data.Latitude);
delete data.Longitude;
delete data.Latitude;
const position = Cartesian3.fromDegrees(longitude, latitude, -depthMeters);
const posCart = Cartographic.fromCartesian(position);
const altitude = this.viewer.scene.globe.getHeight(posCart) || 0;
posCart.height = posCart.height + altitude;
Cartographic.toCartesian(posCart, undefined, position);
const cameraDistance = size * 4;
const zoomHeadingPitchRange = new HeadingPitchRange(0, CMath.toRadians(25), cameraDistance);
data['Details'] = this.config.detailsUrl;
this.boundingRectangle.west = Math.min(CMath.toRadians(longitude), this.boundingRectangle.west);
this.boundingRectangle.south = Math.min(CMath.toRadians(latitude), this.boundingRectangle.south);
this.boundingRectangle.east = Math.max(CMath.toRadians(longitude), this.boundingRectangle.east);
this.boundingRectangle.north = Math.max(CMath.toRadians(latitude), this.boundingRectangle.north);
this.maximumHeight = Math.max(this.maximumHeight, depthMeters * 2);
return this.earthquakeDataSource.entities.add({
position: position,
ellipsoid: {
radii: new Cartesian3(size, size, size),
material: getColorFromTime(data.Time),
},
properties: {
...data,
propsOrder: this.config.propsOrder,
zoomHeadingPitchRange: zoomHeadingPitchRange
}
});
});
this.boundingSphere = BoundingSphere.fromRectangle3D(this.boundingRectangle);
const response = await fetch(this.config.downloadUrl);
const text = await response.text();
parseEarthquakeData(text).map(data => {
const size = Number(data.Magnitude.split(' ')[0]) * EARTHQUAKE_SPHERE_SIZE_COEF;
const depthMeters = Number(data.Depthkm.split(' ')[0]) * 1000; // convert km to m
const longitude = Number(data.Longitude);
const latitude = Number(data.Latitude);
delete data.Longitude;
delete data.Latitude;
const position = Cartesian3.fromDegrees(longitude, latitude, -depthMeters);
const posCart = Cartographic.fromCartesian(position);
const altitude = this.viewer.scene.globe.getHeight(posCart) || 0;
posCart.height = posCart.height + altitude;
Cartographic.toCartesian(posCart, undefined, position);
const cameraDistance = size * 4;
const zoomHeadingPitchRange = new HeadingPitchRange(0, CMath.toRadians(25), cameraDistance);
data['Details'] = this.config.detailsUrl;
this.boundingRectangle.west = Math.min(CMath.toRadians(longitude), this.boundingRectangle.west);
this.boundingRectangle.south = Math.min(CMath.toRadians(latitude), this.boundingRectangle.south);
this.boundingRectangle.east = Math.max(CMath.toRadians(longitude), this.boundingRectangle.east);
this.boundingRectangle.north = Math.max(CMath.toRadians(latitude), this.boundingRectangle.north);
this.maximumHeight = Math.max(this.maximumHeight, depthMeters * 2);
return this.earthquakeDataSource.entities.add({
position: position,
ellipsoid: {
radii: new Cartesian3(size, size, size),
material: getColorFromTime(data.Time),
},
properties: {
...data,
propsOrder: this.config.propsOrder,
zoomHeadingPitchRange: zoomHeadingPitchRange
}
});
});
this.boundingSphere = BoundingSphere.fromRectangle3D(this.boundingRectangle);
}

/**
Expand Down
1 change: 0 additions & 1 deletion ui/src/elements/dashboard/ngm-dashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,6 @@ export class NgmDashboard extends LitElementI18n {
const name = await parseKml(this.viewer, href, uploadedLayer, !!asset.clampToGround);
this.assetConfigs[href] = {
label: name,
zoomToBbox: true,
opacity: DEFAULT_LAYER_OPACITY,
notSaveToPermalink: true,
topicKml: true
Expand Down
14 changes: 2 additions & 12 deletions ui/src/elements/ngm-side-bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,9 @@ import './ngm-share-link';
import '../layers/ngm-layers-upload';
import MainStore from '../store/main';
import {classMap} from 'lit/directives/class-map.js';
import {zoomTo} from '../utils';
import $ from '../jquery';
import {customElement, property, query, state} from 'lit/decorators.js';
import type QueryManager from '../query/QueryManager';
import NavToolsStore from '../store/navTools';

import DashboardStore from '../store/dashboard';
import {getAssets} from '../api-ion';
Expand Down Expand Up @@ -295,20 +293,13 @@ export class SideBar extends LitElementI18n {
html`
<ngm-layers-sort
.layers=${this.activeLayers}
@orderChanged=${(evt) => this.onLayersOrderChange(evt.detail)}
@zoomTo=${evt => {
NavToolsStore.hideTargetPoint();
zoomTo(this.viewer!, evt.detail);
}}>
.actions=${this.layerActions}
@orderChanged=${(evt) => this.onLayersOrderChange(evt.detail)}>
</ngm-layers-sort>` :
html`
<ngm-layers
.layers=${this.activeLayers}
.actions=${this.layerActions}
@zoomTo=${evt => {
NavToolsStore.hideTargetPoint();
zoomTo(this.viewer!, evt.detail);
}}
@removeDisplayedLayer=${evt => this.onRemoveDisplayedLayer(evt)}
@layerChanged=${evt => this.onLayerChanged(evt)}>
</ngm-layers>`
Expand Down Expand Up @@ -726,7 +717,6 @@ export class SideBar extends LitElementI18n {
label: name,
layer,
promise: promise,
zoomToBbox: true,
opacity: DEFAULT_LAYER_OPACITY,
notSaveToPermalink: true,
ownKml: true,
Expand Down
51 changes: 38 additions & 13 deletions ui/src/layers/LayersActions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {syncLayersParam} from '../permalink';
import {calculateBox, calculateRectangle, getBoxFromRectangle} from './helpers';
import {LayerType} from '../constants';
import {LayerType, MAP_RECTANGLE} from '../constants';
import {
Cartesian3,
Rectangle,
Expand All @@ -9,7 +9,7 @@ import {
Cesium3DTileset,
ImageryLayer,
CustomDataSource,
GeoJsonDataSource
GeoJsonDataSource, VoxelPrimitive
} from 'cesium';
import type {Viewer} from 'cesium';

Expand Down Expand Up @@ -61,29 +61,46 @@ export default class LayersAction {
const p = await config.promise;
// wrong type in cesium;
const rootBoundingVolume = (<any> p)?.root?.boundingVolume;
if (p instanceof EarthquakeVisualizer && p.boundingRectangle) { // earthquakes
this.boundingBoxEntity.position = Cartographic.toCartesian(Rectangle.center(p.boundingRectangle));
this.boundingBoxEntity.box.dimensions = getBoxFromRectangle(p.boundingRectangle, p.maximumHeight);
this.boundingBoxEntity.rectangle.coordinates = p.boundingRectangle;
this.boundingBoxEntity.show = true;
this.viewer.scene.requestRender();
if (p instanceof EarthquakeVisualizer) { // earthquakes
// fetch earthquakes to get bbox info
if (!isFinite(p.boundingRectangle.west)) {
await p.showEarthquakes();
p.earthquakeDataSource.show = false;
}
this.showBbox(p.boundingRectangle, p.maximumHeight, true);
} else if ((p instanceof Cesium3DTileset) && rootBoundingVolume) {
const boundingVolume = rootBoundingVolume.boundingVolume;
const boundingRectangle = rootBoundingVolume.rectangle;
this.boundingBoxEntity.position = boundingVolume.center;
if (boundingRectangle) {
this.boundingBoxEntity.position = boundingVolume.center;
this.boundingBoxEntity.box.dimensions = getBoxFromRectangle(boundingRectangle, rootBoundingVolume.maximumHeight);
this.boundingBoxEntity.rectangle.coordinates = boundingRectangle;
this.boundingBoxEntity.show = true;
this.viewer.scene.requestRender();
} else {
const boxSize = calculateBox(boundingVolume.halfAxes, p.root.boundingSphere.radius);
this.boundingBoxEntity.box.dimensions = boxSize;
this.boundingBoxEntity.rectangle.coordinates = calculateRectangle(boxSize.x, boxSize.y, boundingVolume.center);
const boundingRectangle = calculateRectangle(boxSize.x, boxSize.y, boundingVolume.center);
this.showBbox(boundingRectangle, boxSize.z);
}
this.boundingBoxEntity.show = true;
this.viewer.scene.requestRender();
} else if (p instanceof ImageryLayer) {
this.showBbox(p.imageryProvider.rectangle, 20000);
} else if (p instanceof VoxelPrimitive) {
const boxSize = calculateBox(p.orientedBoundingBox.halfAxes, p.boundingSphere.radius);
const boundingRectangle = calculateRectangle(boxSize.x, boxSize.y, p.orientedBoundingBox.center);
this.showBbox(boundingRectangle, boxSize.z);
}
}

private showBbox(boundingRectangle: Rectangle, height: number = 0, skipIntersectionCheck: boolean = false) {
if (!boundingRectangle) return;
if (!skipIntersectionCheck) Rectangle.intersection(MAP_RECTANGLE, boundingRectangle, boundingRectangle);
this.boundingBoxEntity.position = Cartographic.toCartesian(Rectangle.center(boundingRectangle));
this.boundingBoxEntity.box.dimensions = getBoxFromRectangle(boundingRectangle, height);
this.boundingBoxEntity.rectangle.coordinates = boundingRectangle;
this.boundingBoxEntity.show = true;
this.viewer.scene.requestRender();
}

hideBoundingBox() {
if (this.boundingBoxEntity.show) {
this.boundingBoxEntity.show = false;
Expand Down Expand Up @@ -114,4 +131,12 @@ export default class LayersAction {
stuff[eventName].addEventListener(callback);
}
}

zoomToBbox() {
this.viewer.zoomTo(this.boundingBoxEntity, {
heading: 0,
pitch: -1.57079633,
range: 0
});
}
}
6 changes: 4 additions & 2 deletions ui/src/layers/ngm-layers-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,14 +250,16 @@ export class NgmLayersItem extends LitElementI18n {
</div>
<div class="ngm-displayed-menu">
<div title=${i18next.t('dtd_zoom_to')}
class="ngm-layer-icon ngm-zoom-plus-icon" ?hidden=${!this.config.zoomToBbox}
class="ngm-layer-icon ngm-zoom-plus-icon"
@mouseenter=${() => {
if (this.actions && this.actions.showBoundingBox) this.actions.showBoundingBox(this.config);
}}
@mouseleave=${() => {
if (this.actions && this.actions.hideBoundingBox) this.actions.hideBoundingBox();
}}
@click=${() => this.dispatchEvent(new CustomEvent('zoomTo'))}>
@click=${() => {
if (this.actions && this.actions.zoomToBbox) this.actions.zoomToBbox();
}}>
</div>
<div title=${i18next.t('dtd_remove')}
class="ngm-layer-icon ngm-delete-icon ${classMap({disabled: this.changeOrderActive})}"
Expand Down
4 changes: 3 additions & 1 deletion ui/src/layers/ngm-layers-sort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Sortable.mount(new MultiDrag());
export default class NgmLayersSort extends LitElementI18n {
@property({type: Array})
accessor layers: LayerConfig[] = [];
@property({type: Object})
accessor actions: any;
private sortable: Sortable;
private sortedList: LayerConfig[] = [];

Expand Down Expand Up @@ -73,7 +75,7 @@ export default class NgmLayersSort extends LitElementI18n {
<ngm-layers-item
.config=${config}
.changeOrderActive=${true}
@zoomTo=${() => this.dispatchEvent(new CustomEvent('zoomTo', {detail: config}))}
.actions=${this.actions}
>
</ngm-layers-item>
`;
Expand Down
1 change: 0 additions & 1 deletion ui/src/layers/ngm-layers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ export default class NgmLayers extends LitElementI18n {
@removeDisplayedLayer=${() => {
this.dispatchEvent(new CustomEvent('removeDisplayedLayer', {detail}));
}}
@zoomTo=${() => this.dispatchEvent(new CustomEvent('zoomTo', {detail: config}))}
@layerChanged=${() => this.dispatchEvent(new CustomEvent('layerChanged', {detail: config}))}
>
</ngm-layers-item>
Expand Down
13 changes: 0 additions & 13 deletions ui/src/layertree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ export interface LayerTreeNode {
// Normally, visible => displayed
visible?: boolean;
pickable?: boolean;
zoomToBbox?: boolean;
opacity?: number;
opacityDisabled?: boolean;
style?: any;
Expand Down Expand Up @@ -659,7 +658,6 @@ const geo_base: LayerTreeNode = {
visible: false,
displayed: true,
pickable: true,
zoomToBbox: true,
geocatId: '2924c78a-8f1e-4eb4-b6f6-0fb2405fa7df',
},
{
Expand All @@ -683,7 +681,6 @@ const geo_base: LayerTreeNode = {
visible: false,
displayed: false,
pickable: true,
zoomToBbox: true,
propsOrder: ['CS-AAT-Cross-section', 'CS-AAT-Lithostratigraphy', 'CS-AAT-Type', 'CS-AAT-Legend', 'CS-AAT-Report'],
geocatId: 'ab34eb52-30c4-4b69-840b-ef41f47f9e9a',
}
Expand All @@ -707,7 +704,6 @@ const geo_energy: LayerTreeNode = {
layer: 'temperature_model',
opacityDisabled: true,
pickable: true,
zoomToBbox: false,
geocatId: '63ed59b1-d9fb-4c6e-a629-550c8f6b9bf2',
},
{
Expand Down Expand Up @@ -881,7 +877,6 @@ const subsurface: LayerTreeNode = {
layer: 'voxel_aaretal_litho',
opacityDisabled: true,
pickable: true,
zoomToBbox: true,
downloadUrl: DOWNLOAD_ROOT_VOXEL + 'legends/Vox-Aaretal-Legende.pdf',
geocatId: 'b1a36f66-638a-4cfb-88d3-b0df6c7a7502',
},
Expand All @@ -895,7 +890,6 @@ const subsurface: LayerTreeNode = {
layer: 'voxel_aaretal_logk',
opacityDisabled: true,
pickable: true,
zoomToBbox: true,
downloadUrl: DOWNLOAD_ROOT_VOXEL + 'legends/Vox-Aaretal-Legende.pdf',
geocatId: '9471ee1b-5811-489d-b050-612c011f9d57',
},
Expand All @@ -909,7 +903,6 @@ const subsurface: LayerTreeNode = {
layer: 'voxel_birrfeld_litho',
opacityDisabled: true,
pickable: true,
zoomToBbox: true,
downloadUrl: DOWNLOAD_ROOT_VOXEL + 'legends/Vox-Birrfeld-Legende.pdf',
geocatId: 'f56c9c6c-ff59-463d-ba66-477fd2d92f39',
},
Expand All @@ -923,7 +916,6 @@ const subsurface: LayerTreeNode = {
layer: 'voxel_birrfeld_logk',
opacityDisabled: true,
pickable: true,
zoomToBbox: true,
downloadUrl: DOWNLOAD_ROOT_VOXEL + 'legends/Vox-Birrfeld-Legende.pdf',
geocatId: '96f923d6-a747-481b-a0d8-2cfec321170e',
},
Expand All @@ -937,7 +929,6 @@ const subsurface: LayerTreeNode = {
layer: 'voxel_geneva_litho',
opacityDisabled: true,
pickable: true,
zoomToBbox: true,
downloadUrl: DOWNLOAD_ROOT_VOXEL + 'legends/Vox-GVA-Legende.pdf',
geocatId: '697f4c99-ed1b-4901-bc87-3710fcce1352',
},
Expand All @@ -951,7 +942,6 @@ const subsurface: LayerTreeNode = {
layer: 'voxel_geneva_logk',
opacityDisabled: true,
pickable: true,
zoomToBbox: true,
downloadUrl: DOWNLOAD_ROOT_VOXEL + 'legends/Vox-GVA-Legende.pdf',
geocatId: '4a4a530f-6a2a-423d-834e-2831d70fde20',
},
Expand All @@ -965,7 +955,6 @@ const subsurface: LayerTreeNode = {
layer: 'voxel_visp_litho',
opacityDisabled: true,
pickable: true,
zoomToBbox: true,
downloadUrl: DOWNLOAD_ROOT_VOXEL + 'legends/Vox-Visp-Legende.pdf',
geocatId: 'b621de46-2553-4fb2-88b4-f770e0243299',
},
Expand All @@ -979,7 +968,6 @@ const subsurface: LayerTreeNode = {
layer: 'voxel_visp_logk',
opacityDisabled: true,
pickable: true,
zoomToBbox: true,
downloadUrl: DOWNLOAD_ROOT_VOXEL + 'legends/Vox-Visp-Legende.pdf',
geocatId: 'f7847c2c-bd3a-4dda-99c7-d50453b24c3d',
},
Expand Down Expand Up @@ -1204,7 +1192,6 @@ const subsurface: LayerTreeNode = {
layer: '3d_model_berne',
opacity: DEFAULT_LAYER_OPACITY,
pickable: true,
zoomToBbox: true,
propsOrder: ['3DBern-Unit', '3DBern-Link', '3DBern-Lithology', '3DBern-TectonicUnit',
'3DBern-ChronoB-T', '3DBern-OrigDesc', '3DBern-Version', '3DBern-Aothor', '3DBern-Purpose',
'3DBern-Download'],
Expand Down
Loading

0 comments on commit 8af06a1

Please sign in to comment.