From d083713ebdddc4f084152e665a5dee8663c06da1 Mon Sep 17 00:00:00 2001 From: Sandro Mani Date: Mon, 6 Jan 2025 18:32:31 +0100 Subject: [PATCH] Add initial Compare3D component --- components/map3d/Compare3D.jsx | 193 +++++++++++++++++++++++++++ components/map3d/Map3D.jsx | 2 + components/map3d/TopBar3D.jsx | 1 + components/map3d/style/Compare3D.css | 57 ++++++++ icons/compare.svg | 72 ++++++++++ translations/ca-ES.json | 7 + translations/cs-CZ.json | 7 + translations/de-CH.json | 7 + translations/de-DE.json | 7 + translations/en-US.json | 7 + translations/es-ES.json | 7 + translations/fi-FI.json | 7 + translations/fr-FR.json | 7 + translations/hu-HU.json | 7 + translations/it-IT.json | 7 + translations/no-NO.json | 7 + translations/pl-PL.json | 7 + translations/pt-BR.json | 7 + translations/pt-PT.json | 7 + translations/ro-RO.json | 7 + translations/ru-RU.json | 7 + translations/sv-SE.json | 7 + translations/tr-TR.json | 7 + translations/tsconfig.json | 5 + 24 files changed, 456 insertions(+) create mode 100644 components/map3d/Compare3D.jsx create mode 100644 components/map3d/style/Compare3D.css create mode 100644 icons/compare.svg diff --git a/components/map3d/Compare3D.jsx b/components/map3d/Compare3D.jsx new file mode 100644 index 000000000..39939cb45 --- /dev/null +++ b/components/map3d/Compare3D.jsx @@ -0,0 +1,193 @@ +/** + * Copyright 2024 Sourcepole AG + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React from 'react'; + +import PropTypes from 'prop-types'; +import {Plane, Vector3} from 'three'; + +import LocaleUtils from '../../utils/LocaleUtils'; +import Icon from '../Icon'; +import SideBar from '../SideBar'; +import NumberInput from '../widgets/NumberInput'; + +import './style/Compare3D.css'; + + +export default class Compare3D extends React.Component { + static propTypes = { + sceneContext: PropTypes.object + }; + state = { + enabled: false, + clippedObjects: {}, + planeX: 0, + planeY: 0, + planeA: 0 + }; + componentWillUnmount() { + this.clearClippingPlane(); + } + componentDidUpdate(prevProps, prevState) { + if (this.state.enabled && this.state !== prevState) { + // Recompute clipping plane + this.updateClippingPlane(); + } else if (!this.state.enabled && prevState.enabled) { + this.clearClippingPlane(); + } + } + updateClippingPlane = () => { + const point = new Vector3(this.state.planeX, this.state.planeY, 0); + const alpha = this.state.planeA / 180 * Math.PI; + const normal = new Vector3(Math.sin(alpha), Math.cos(alpha), 0); + const leftPlane = new Plane(); + const rightPlane = new Plane(); + leftPlane.setFromNormalAndCoplanarPoint(normal, point); + rightPlane.setFromNormalAndCoplanarPoint(-normal, point); + Object.entries(this.state.clippedObjects).forEach(([objectId, config]) => { + const planes = []; + if (config.left) { + planes.push(leftPlane); + } + if (config.right) { + planes.push(rightPlane); + } + if (objectId === "__terrain") { + this.props.sceneContext.map.clippingPlanes = planes; + } else { + this.props.sceneContext.getSceneObject(objectId).clippingPlanes = planes; + } + }); + this.props.sceneContext.scene.notifyChange(); + }; + clearClippingPlane = () => { + Object.keys(this.state.clippedObjects).forEach(objectId => { + if (objectId === "__terrain") { + this.props.sceneContext.map.clippingPlanes = []; + } else { + this.props.sceneContext.getSceneObject(objectId).clippingPlanes = []; + } + }); + this.props.sceneContext.scene.notifyChange(); + }; + render() { + return ( +
+ + {() => ({ + body: this.renderBody() + })} + +
+ ); + } + renderBody = () => { + const sceneContext = this.props.sceneContext; + const objects = {__terrain: {layertree: true, title: LocaleUtils.tr("map3d.terrain")}, ...sceneContext.sceneObjects}; + const objectIds = Object.keys(objects).filter(objectId => objects[objectId].layertree); + return ( +
+
+ + {LocaleUtils.tr("compare3d.compare_objects")} +
+
+ {["left", "right"].map(section => { + const clipState = this.state.clippedObjects; + let toggleAllIcon = "checked"; + let toggleAllValue = true; + const toggleAllState = objectIds.reduce((res, id) => res + clipState[id]?.[section], 0); + if (toggleAllState === objectIds.length) { + toggleAllIcon = "unchecked"; + toggleAllValue = false; + } else if (toggleAllState > 0) { + toggleAllIcon = "tristate"; + } + return ( +
+
this.toggleAllObjects(section, objectIds, toggleAllValue)} + title={LocaleUtils.tr("compare3d.toggleall")} + > + + {LocaleUtils.tr("compare3d.toggleall")} +
+ {objectIds.map(objectId => ( +
this.toggleObject(section, objectId)} + title={objects[objectId].title ?? objectId} + > + + {objects[objectId].title ?? objectId} +
+ ))} +
+ ); + })} +
+
{LocaleUtils.tr("compare3d.clipplane")}
+ + + + + + + + + + + + + + + +
x this.setState({planeX: x})} value={this.state.planeX}/>
y this.setState({planeY: y})} value={this.state.planeY}/>
α this.setState({planeA: a})} suffix="°" value={this.state.planeA} />
+
+ ); + }; + toggleCompare = () => { + this.setState(state => { + const newState = {enabled: !state.enabled}; + if (newState.enabled) { + // Position plane in current view + newState.planeX = this.props.sceneContext.scene.view.controls.target.x; + newState.planeY = this.props.sceneContext.scene.view.controls.target.y; + newState.planeA = -this.props.sceneContext.scene.view.controls.getAzimuthalAngle() / Math.PI * 180 + 90; + } + return newState; + }); + }; + toggleObject = (section, objectId) => { + this.setState(state => ({ + clippedObjects: { + ...state.clippedObjects, + [objectId]: { + ...state.clippedObjects[objectId], + [section]: !state.clippedObjects[objectId]?.[section] + } + } + })); + }; + toggleAllObjects = (section, objectIds, value) => { + this.setState(state => ({ + clippedObjects: objectIds.reduce((res, objectId) => ({ + ...res, + [objectId]: { + ...state.clippedObjects[objectId], + [section]: value + } + }), {}) + })); + }; +} diff --git a/components/map3d/Map3D.jsx b/components/map3d/Map3D.jsx index ce72c457d..94437a29c 100644 --- a/components/map3d/Map3D.jsx +++ b/components/map3d/Map3D.jsx @@ -30,6 +30,7 @@ import CoordinatesUtils from '../../utils/CoordinatesUtils'; import MiscUtils from '../../utils/MiscUtils'; import Icon from '../Icon'; import BottomBar3D from './BottomBar3D'; +import Compare3D from './Compare3D'; import LayerTree3D from './LayerTree3D'; import Map3DLight from './Map3DLight'; import Measure3D from './Measure3D'; @@ -339,6 +340,7 @@ class Map3D extends React.Component { + ) : null} diff --git a/components/map3d/TopBar3D.jsx b/components/map3d/TopBar3D.jsx index d5348a8f3..8808a7d14 100644 --- a/components/map3d/TopBar3D.jsx +++ b/components/map3d/TopBar3D.jsx @@ -32,6 +32,7 @@ class TopBar3D extends React.Component { const menuItems = [ {key: "LayerTree3D", icon: "layers"}, {key: "Measure3D", icon: "measure"}, + {key: "Compare3D", icon: "compare"}, {key: "DateTime3D", icon: "clock"} ]; return ( diff --git a/components/map3d/style/Compare3D.css b/components/map3d/style/Compare3D.css new file mode 100644 index 000000000..3986f3814 --- /dev/null +++ b/components/map3d/style/Compare3D.css @@ -0,0 +1,57 @@ +#Compare3D div.compare3d-title { + display: flex; + align-items: center; + padding: 0 0.125em; +} + +#Compare3D div.compare3d-title > span.icon { + margin-right: 0.5em; +} + +#Compare3D div.compare3d-objects { + display: flex; + background-color: var(--list-bg-color); + margin: 0.25em; +} + +#Compare3D div.compare3d-section { + flex: 1 1 auto; + border: 1px solid var(--border-color); +} + +#Compare3D div.compare3d-section:first-child { + border-right: 1px solid var(--border-color); +} + +#Compare3D div.compare3d-section:last-child { + border-left: 1px solid var(--border-color); +} + +#Compare3D div.compare3d-item { + display: flex; + align-items: center; + padding: 0.25em; +} + +#Compare3D div.compare3d-item-toggleall { + border-bottom: 1px solid var(--border-color); +} + +#Compare3D span.compare3d-item-checkbox { + margin-right: 0.5em; + flex: 0 0 auto; +} + +#Compare3D div.compare3d-title { + font-weight: bold; + margin: 0.25em; +} + +#Compare3D table.compare3d-planeconfig { + width: 100%; + margin-bottom: 0.25em; +} + +#Compare3D table.compare3d-planeconfig td { + padding: 0 0.25em 0 0.5em; +} \ No newline at end of file diff --git a/icons/compare.svg b/icons/compare.svg new file mode 100644 index 000000000..1ac4f90ce --- /dev/null +++ b/icons/compare.svg @@ -0,0 +1,72 @@ + + + + + + + + image/svg+xml + + uniE094 + + + + + + + + uniE094 + + diff --git a/translations/ca-ES.json b/translations/ca-ES.json index ddd140451..d33c4e9b2 100644 --- a/translations/ca-ES.json +++ b/translations/ca-ES.json @@ -12,6 +12,7 @@ "filter": "Menú de filtres...", "items": { "Bookmark": "Marcador", + "Compare3D": "", "DateTime3D": "", "Editing": "Edició", "Help": "Ajuda", @@ -95,6 +96,11 @@ "terms_label": "Condicions del servei", "viewertitle_label": "" }, + "compare3d": { + "clipplane": "", + "compare_objects": "", + "toggleall": "" + }, "cookiepopup": { "accept": "", "message": "" @@ -277,6 +283,7 @@ }, "map3d": { "syncview": "", + "terrain": "", "title": "" }, "mapexport": { diff --git a/translations/cs-CZ.json b/translations/cs-CZ.json index f67719f9a..2dba4270a 100644 --- a/translations/cs-CZ.json +++ b/translations/cs-CZ.json @@ -12,6 +12,7 @@ "filter": "Hledat v menu...", "items": { "Bookmark": "Záložky", + "Compare3D": "", "DateTime3D": "", "Editing": "Úpravy", "Help": "Nápověda", @@ -95,6 +96,11 @@ "terms_label": "Podmínky použití", "viewertitle_label": "" }, + "compare3d": { + "clipplane": "", + "compare_objects": "", + "toggleall": "" + }, "cookiepopup": { "accept": "", "message": "" @@ -277,6 +283,7 @@ }, "map3d": { "syncview": "", + "terrain": "", "title": "" }, "mapexport": { diff --git a/translations/de-CH.json b/translations/de-CH.json index 89188a388..641b9ae70 100644 --- a/translations/de-CH.json +++ b/translations/de-CH.json @@ -12,6 +12,7 @@ "filter": "Menü filtern...", "items": { "Bookmark": "Lesezeichen", + "Compare3D": "Vergleichen", "DateTime3D": "Datum und Zeit", "Editing": "Editieren", "Help": "Hilfe", @@ -95,6 +96,11 @@ "terms_label": "Nutzungsbedingungen", "viewertitle_label": "" }, + "compare3d": { + "clipplane": "Schnittebene", + "compare_objects": "Objekte vergleichen", + "toggleall": "Alle" + }, "cookiepopup": { "accept": "Akzeptieren", "message": "Diese Seite verwendet Cookies." @@ -277,6 +283,7 @@ }, "map3d": { "syncview": "Ansicht synchronisieren", + "terrain": "Gelände", "title": "3D Ansicht" }, "mapexport": { diff --git a/translations/de-DE.json b/translations/de-DE.json index 506ebc71e..f108f8402 100644 --- a/translations/de-DE.json +++ b/translations/de-DE.json @@ -12,6 +12,7 @@ "filter": "Menü filtern...", "items": { "Bookmark": "Lesezeichen", + "Compare3D": "Vergleichen", "DateTime3D": "Datum und Zeit", "Editing": "Editieren", "Help": "Hilfe", @@ -95,6 +96,11 @@ "terms_label": "Nutzungsbedingungen", "viewertitle_label": "" }, + "compare3d": { + "clipplane": "Schnittebene", + "compare_objects": "Objekte vergleichen", + "toggleall": "Alle" + }, "cookiepopup": { "accept": "Akzeptieren", "message": "Diese Seite verwendet Cookies." @@ -277,6 +283,7 @@ }, "map3d": { "syncview": "Ansicht synchronisieren", + "terrain": "Gelände", "title": "3D Ansicht" }, "mapexport": { diff --git a/translations/en-US.json b/translations/en-US.json index 7c5234894..b019ec451 100644 --- a/translations/en-US.json +++ b/translations/en-US.json @@ -12,6 +12,7 @@ "filter": "Filter menu...", "items": { "Bookmark": "Bookmarks", + "Compare3D": "Compare", "DateTime3D": "Date and Time", "Editing": "Editing", "Help": "Help", @@ -95,6 +96,11 @@ "terms_label": "Terms of use", "viewertitle_label": "" }, + "compare3d": { + "clipplane": "Clipping plane", + "compare_objects": "Compare objects", + "toggleall": "Toggle all" + }, "cookiepopup": { "accept": "Accept", "message": "This website uses cookies." @@ -277,6 +283,7 @@ }, "map3d": { "syncview": "Synchronize view", + "terrain": "Terrain", "title": "3D View" }, "mapexport": { diff --git a/translations/es-ES.json b/translations/es-ES.json index 032549d14..d0d9a9f1e 100644 --- a/translations/es-ES.json +++ b/translations/es-ES.json @@ -12,6 +12,7 @@ "filter": "Menú de filtros...", "items": { "Bookmark": "Marcadores", + "Compare3D": "", "DateTime3D": "", "Editing": "Edición", "Help": "Ayuda", @@ -95,6 +96,11 @@ "terms_label": "Términos de uso", "viewertitle_label": "" }, + "compare3d": { + "clipplane": "", + "compare_objects": "", + "toggleall": "" + }, "cookiepopup": { "accept": "", "message": "" @@ -277,6 +283,7 @@ }, "map3d": { "syncview": "", + "terrain": "", "title": "" }, "mapexport": { diff --git a/translations/fi-FI.json b/translations/fi-FI.json index 7e9cb2086..fa01c0734 100644 --- a/translations/fi-FI.json +++ b/translations/fi-FI.json @@ -12,6 +12,7 @@ "filter": "", "items": { "Bookmark": "Kirjanmerkit", + "Compare3D": "", "DateTime3D": "", "Editing": "Editointi", "Help": "Apua", @@ -95,6 +96,11 @@ "terms_label": "Käyttöehdot", "viewertitle_label": "" }, + "compare3d": { + "clipplane": "", + "compare_objects": "", + "toggleall": "" + }, "cookiepopup": { "accept": "", "message": "" @@ -277,6 +283,7 @@ }, "map3d": { "syncview": "", + "terrain": "", "title": "" }, "mapexport": { diff --git a/translations/fr-FR.json b/translations/fr-FR.json index 2fbac2fcc..f8c620679 100644 --- a/translations/fr-FR.json +++ b/translations/fr-FR.json @@ -12,6 +12,7 @@ "filter": "Filtrer le menu...", "items": { "Bookmark": "Marque-pages", + "Compare3D": "Comparer", "DateTime3D": "Date et heure", "Editing": "Editer", "Help": "Aide", @@ -95,6 +96,11 @@ "terms_label": "Conditions d'utilisation", "viewertitle_label": "" }, + "compare3d": { + "clipplane": "Plan d'écrêtage", + "compare_objects": "Comparer objets", + "toggleall": "Tous" + }, "cookiepopup": { "accept": "Accepter", "message": "Ce site web utilise des cookies." @@ -277,6 +283,7 @@ }, "map3d": { "syncview": "Synchroniser la vue", + "terrain": "Terrain", "title": "Vue 3D" }, "mapexport": { diff --git a/translations/hu-HU.json b/translations/hu-HU.json index f20c41587..7e65038d1 100644 --- a/translations/hu-HU.json +++ b/translations/hu-HU.json @@ -12,6 +12,7 @@ "filter": "", "items": { "Bookmark": "", + "Compare3D": "", "DateTime3D": "", "Editing": "Szerkesztés", "Help": "Segítség", @@ -95,6 +96,11 @@ "terms_label": "Használati feltételek", "viewertitle_label": "" }, + "compare3d": { + "clipplane": "", + "compare_objects": "", + "toggleall": "" + }, "cookiepopup": { "accept": "", "message": "" @@ -277,6 +283,7 @@ }, "map3d": { "syncview": "", + "terrain": "", "title": "" }, "mapexport": { diff --git a/translations/it-IT.json b/translations/it-IT.json index c52b7db70..58c104cdd 100644 --- a/translations/it-IT.json +++ b/translations/it-IT.json @@ -12,6 +12,7 @@ "filter": "Filtra menù...", "items": { "Bookmark": "Segnalibri", + "Compare3D": "Confronta", "DateTime3D": "Data e ora", "Editing": "Strumenti di modifica", "Help": "Aiuto", @@ -95,6 +96,11 @@ "terms_label": "Condizioni di uso", "viewertitle_label": "" }, + "compare3d": { + "clipplane": "Piano di taglio", + "compare_objects": "Confronta oggetti", + "toggleall": "Tutti" + }, "cookiepopup": { "accept": "Accetta", "message": "Questo sito web utilizza cookie." @@ -277,6 +283,7 @@ }, "map3d": { "syncview": "Sincronizza visuale", + "terrain": "Terreno", "title": "Visuale 3D" }, "mapexport": { diff --git a/translations/no-NO.json b/translations/no-NO.json index 58c96427f..93ace746f 100644 --- a/translations/no-NO.json +++ b/translations/no-NO.json @@ -12,6 +12,7 @@ "filter": "", "items": { "Bookmark": "", + "Compare3D": "", "DateTime3D": "", "Editing": "Rediger", "Help": "Hjelp", @@ -95,6 +96,11 @@ "terms_label": "Vilkår", "viewertitle_label": "" }, + "compare3d": { + "clipplane": "", + "compare_objects": "", + "toggleall": "" + }, "cookiepopup": { "accept": "", "message": "" @@ -277,6 +283,7 @@ }, "map3d": { "syncview": "", + "terrain": "", "title": "" }, "mapexport": { diff --git a/translations/pl-PL.json b/translations/pl-PL.json index e999e90dc..c38806691 100644 --- a/translations/pl-PL.json +++ b/translations/pl-PL.json @@ -12,6 +12,7 @@ "filter": "", "items": { "Bookmark": "", + "Compare3D": "", "DateTime3D": "", "Editing": "Edycja", "Help": "Pomoc", @@ -95,6 +96,11 @@ "terms_label": "Warunki korzystania", "viewertitle_label": "" }, + "compare3d": { + "clipplane": "", + "compare_objects": "", + "toggleall": "" + }, "cookiepopup": { "accept": "", "message": "" @@ -277,6 +283,7 @@ }, "map3d": { "syncview": "", + "terrain": "", "title": "" }, "mapexport": { diff --git a/translations/pt-BR.json b/translations/pt-BR.json index bed807171..e4c527db7 100644 --- a/translations/pt-BR.json +++ b/translations/pt-BR.json @@ -12,6 +12,7 @@ "filter": "Filtro", "items": { "Bookmark": "Bookmark", + "Compare3D": "", "DateTime3D": "", "Editing": "Edição", "Help": "Ajuda", @@ -95,6 +96,11 @@ "terms_label": "Termos de uso", "viewertitle_label": "" }, + "compare3d": { + "clipplane": "", + "compare_objects": "", + "toggleall": "" + }, "cookiepopup": { "accept": "", "message": "" @@ -277,6 +283,7 @@ }, "map3d": { "syncview": "", + "terrain": "", "title": "" }, "mapexport": { diff --git a/translations/pt-PT.json b/translations/pt-PT.json index 6cc100cdd..156e34c95 100644 --- a/translations/pt-PT.json +++ b/translations/pt-PT.json @@ -12,6 +12,7 @@ "filter": "Filtro", "items": { "Bookmark": "Marcador", + "Compare3D": "", "DateTime3D": "", "Editing": "Edição", "Help": "Ajuda", @@ -95,6 +96,11 @@ "terms_label": "Termos de Uso", "viewertitle_label": "Visualizador" }, + "compare3d": { + "clipplane": "", + "compare_objects": "", + "toggleall": "" + }, "cookiepopup": { "accept": "", "message": "" @@ -277,6 +283,7 @@ }, "map3d": { "syncview": "", + "terrain": "", "title": "" }, "mapexport": { diff --git a/translations/ro-RO.json b/translations/ro-RO.json index 441b8d6ba..3bf2a56d0 100644 --- a/translations/ro-RO.json +++ b/translations/ro-RO.json @@ -12,6 +12,7 @@ "filter": "", "items": { "Bookmark": "Marcaj", + "Compare3D": "", "DateTime3D": "", "Editing": "Editare", "Help": "Ajutor", @@ -95,6 +96,11 @@ "terms_label": "Termeni de utilizare", "viewertitle_label": "Despre" }, + "compare3d": { + "clipplane": "", + "compare_objects": "", + "toggleall": "" + }, "cookiepopup": { "accept": "", "message": "" @@ -277,6 +283,7 @@ }, "map3d": { "syncview": "", + "terrain": "", "title": "" }, "mapexport": { diff --git a/translations/ru-RU.json b/translations/ru-RU.json index 294c9b4bc..c1ff74306 100644 --- a/translations/ru-RU.json +++ b/translations/ru-RU.json @@ -12,6 +12,7 @@ "filter": "", "items": { "Bookmark": "", + "Compare3D": "", "DateTime3D": "", "Editing": "Правка", "Help": "Помощь", @@ -95,6 +96,11 @@ "terms_label": "Условия использования", "viewertitle_label": "Домашняя страница" }, + "compare3d": { + "clipplane": "", + "compare_objects": "", + "toggleall": "" + }, "cookiepopup": { "accept": "", "message": "" @@ -277,6 +283,7 @@ }, "map3d": { "syncview": "", + "terrain": "", "title": "" }, "mapexport": { diff --git a/translations/sv-SE.json b/translations/sv-SE.json index ad57eff2c..554a442fc 100644 --- a/translations/sv-SE.json +++ b/translations/sv-SE.json @@ -12,6 +12,7 @@ "filter": "", "items": { "Bookmark": "", + "Compare3D": "", "DateTime3D": "", "Editing": "Redigera", "Help": "Hjälp", @@ -95,6 +96,11 @@ "terms_label": "Villkor", "viewertitle_label": "" }, + "compare3d": { + "clipplane": "", + "compare_objects": "", + "toggleall": "" + }, "cookiepopup": { "accept": "", "message": "" @@ -277,6 +283,7 @@ }, "map3d": { "syncview": "", + "terrain": "", "title": "" }, "mapexport": { diff --git a/translations/tr-TR.json b/translations/tr-TR.json index cbb10e674..6245fe0b4 100644 --- a/translations/tr-TR.json +++ b/translations/tr-TR.json @@ -12,6 +12,7 @@ "filter": "Filtre menüsü...", "items": { "Bookmark": "Yer işaretleri", + "Compare3D": "", "DateTime3D": "", "Editing": "Düzenleme", "Help": "Yardım", @@ -95,6 +96,11 @@ "terms_label": "Kullanım Şartları", "viewertitle_label": "QWC2" }, + "compare3d": { + "clipplane": "", + "compare_objects": "", + "toggleall": "" + }, "cookiepopup": { "accept": "Kabul", "message": "Bu web sitesi çerez kullanıyor." @@ -277,6 +283,7 @@ }, "map3d": { "syncview": "", + "terrain": "", "title": "" }, "mapexport": { diff --git a/translations/tsconfig.json b/translations/tsconfig.json index eca7bedc3..5e06b7d95 100644 --- a/translations/tsconfig.json +++ b/translations/tsconfig.json @@ -53,6 +53,7 @@ "app.missingtheme", "appmenu.filter", "appmenu.items.Bookmark", + "appmenu.items.Compare3D", "appmenu.items.DateTime3D", "appmenu.items.Editing", "appmenu.items.Help", @@ -105,6 +106,9 @@ "bottombar.scale_label", "bottombar.terms_label", "bottombar.viewertitle_label", + "compare3d.clipplane", + "compare3d.compare_objects", + "compare3d.toggleall", "cookiepopup.accept", "cookiepopup.message", "copybtn.click_to_copy", @@ -244,6 +248,7 @@ "map.loading", "map.resetrotation", "map3d.syncview", + "map3d.terrain", "map3d.title", "mapexport.configuration", "mapexport.format",