Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Release v1.22.0 - #minor #891

Merged
merged 29 commits into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
1d3fa13
PB-521: Enabled geolocation high accuracy
ltshb Jun 6, 2024
0cbcb97
Merge pull request #882 from geoadmin/bug-PB-521-goelocation-high-pre…
ltshb Jun 6, 2024
1a96b2a
PB-574: Fix layers parameter issue at startup
ltshb Jun 4, 2024
f2ea5bb
PB-574: Don't overwrite layer default opacity
ltshb Jun 6, 2024
b762511
Merge pull request #879 from geoadmin/bug-PB-574-layers-param
ltshb Jun 6, 2024
ab70ef6
PB-534: transparency slider works in real time
ltkum May 27, 2024
6a678d6
PB 534: using debounce method for transparency slider
ltkum Jun 7, 2024
808ed7e
Merge pull request #865 from geoadmin/bugfix-PB-534-real-time-opacity…
ltkum Jun 7, 2024
ee82588
PB-562 : do not force drawing module's style onto external KMLs
pakb Jun 6, 2024
b5dfb2f
PB-562 : rework of print tests so that they load non external KMLs
pakb Jun 7, 2024
f28c7f3
Merge pull request #884 from geoadmin/bug_PB-562_wrong_external_kml_s…
pakb Jun 10, 2024
8f2138b
PB-591 : 3D KML improvements
pakb Jun 7, 2024
31f1333
Merge pull request #885 from geoadmin/bug_PB-591_3d_kml_improvments
pakb Jun 10, 2024
e9ea219
PB-548 : fix camera position present in URL at startup issue
pakb Jun 10, 2024
f4cd7e5
PB-548 : if no pitch is given while parsing a legacy camera we look down
pakb Jun 7, 2024
9cdb807
Merge pull request #881 from geoadmin/bug_PB-548_camera_after_reload
pakb Jun 10, 2024
ea19810
PB-575: Properly handle geometry collections for feature highlightning
LukasJoss Jun 6, 2024
60e1565
PB-575: Change default position of map popover with time slider
LukasJoss Jun 6, 2024
e251c38
PB-575: Update map popover limit to account for time slider
LukasJoss Jun 6, 2024
4cd72a4
PB-575: Add dropdown time-slider view for phones
LukasJoss Jun 7, 2024
3d55797
PB-575: Change default position for map popover for time slider dropdown
LukasJoss Jun 7, 2024
c3a40e8
PB-575: Update cypress test to run on Desktop viewport
LukasJoss Jun 10, 2024
629dca5
Merge pull request #883 from geoadmin/fix-PB-575-html-popup-tooltip-i…
LukasJoss Jun 10, 2024
abc3d04
PB-517, PB-588: Fixed legacy X/Y or E/N parameter in LV95 not transla…
ltshb Jun 10, 2024
a03ff0c
PB-588: Fixed legacy X/Y parameter in LV03
ltshb Jun 10, 2024
24c1956
PB-588: Fixed and extended E2E tests for E/N and X/Y legacy parameters
ltshb Jun 10, 2024
0a1f6e3
Merge pull request #890 from geoadmin/bug-PB-517-legacy-center
ltshb Jun 10, 2024
7088d98
PB-583 : use backend service to get LV03 <> LV95 conversion right
pakb Jun 10, 2024
2f1ab9f
Merge pull request #887 from geoadmin/feat_PB-583_use_backend_to_get_…
pakb Jun 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions src/api/lv03Reframe.api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import axios from 'axios'
import proj4 from 'proj4'

import { LV03, LV95 } from '@/utils/coordinates/coordinateSystems'
import log from '@/utils/logging'

const REFRAME_BASE_URL = 'https://geodesy.geo.admin.ch/reframe/'

/**
* Re-frames LV95 coordinate taking all LV03 -> LV95 deformation into account (they are not stable,
* so using "simple" proj4 matrices isn't enough to get a very accurate result)
*
* @param {[Number, Number]} lv95coordinate LV95 coordinate that we want expressed in LV03
* @returns {Promise<[Number, Number]>} Input LV95 coordinate re-framed by the backend service into
* LV03 coordinate
* @see https://www.swisstopo.admin.ch/en/rest-api-geoservices-reframe-web
* @see https://github.com/geoadmin/mf-geoadmin3/blob/master/src/components/ReframeService.js
*/
export default function reframe(lv95coordinate) {
return new Promise((resolve, reject) => {
if (!Array.isArray(lv95coordinate) || lv95coordinate.length !== 2) {
reject(new Error('lv95coordinate must be an array with length of 2'))
}
axios({
method: 'GET',
url: `${REFRAME_BASE_URL}lv95tolv03`,
params: {
easting: lv95coordinate[0],
northing: lv95coordinate[1],
},
})
.then((response) => {
if (response.data?.coordinates) {
resolve(response.data.coordinates)
} else {
log.error(
'Error while re-framing coordinate',
lv95coordinate,
'fallback to proj4'
)
resolve(proj4(LV95.epsg, LV03.epsg, lv95coordinate))
}
})
.catch((error) => {
log.error('Error while re-framing coordinate', lv95coordinate, error)
reject(error)
})
})
}
20 changes: 18 additions & 2 deletions src/modules/map/components/LocationPopupPosition.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { computed, onMounted, ref, toRefs, watch } from 'vue'
import { useI18n } from 'vue-i18n'

import { requestHeight } from '@/api/height.api'
import reframe from '@/api/lv03Reframe.api'
import { registerWhat3WordsLocation } from '@/api/what3words.api'
import CoordinateCopySlot from '@/utils/components/CoordinateCopySlot.vue'
import {
Expand All @@ -15,7 +16,7 @@ import {
UTMFormat,
WGS84Format,
} from '@/utils/coordinates/coordinateFormat'
import { WGS84 } from '@/utils/coordinates/coordinateSystems'
import { LV03, LV95, WGS84 } from '@/utils/coordinates/coordinateSystems'
import log from '@/utils/logging'

const props = defineProps({
Expand All @@ -38,6 +39,7 @@ const props = defineProps({
})
const { coordinate, clickInfo, projection, currentLang } = toRefs(props)

const lv03Coordinate = ref(null)
const what3Words = ref(null)
const height = ref(null)

Expand Down Expand Up @@ -69,13 +71,15 @@ const heightInMeter = computed(() => {

onMounted(() => {
if (clickInfo.value) {
updateLV03Coordinate()
updateWhat3Word()
updateHeight()
}
})

watch(clickInfo, (newClickInfo) => {
if (newClickInfo) {
updateLV03Coordinate()
updateWhat3Word()
updateHeight()
}
Expand All @@ -84,6 +88,16 @@ watch(currentLang, () => {
updateWhat3Word()
})

async function updateLV03Coordinate() {
try {
const lv95coordinate = proj4(projection.value.epsg, LV95.epsg, coordinate.value)
lv03Coordinate.value = await reframe(lv95coordinate)
} catch (error) {
log.error('Failed to retrieve LV03 coordinate', error)
lv03Coordinate.value = null
}
}

async function updateWhat3Word() {
try {
what3Words.value = await registerWhat3WordsLocation(
Expand Down Expand Up @@ -119,9 +133,11 @@ async function updateHeight() {
</a>
</CoordinateCopySlot>
<CoordinateCopySlot
v-if="lv03Coordinate"
identifier="location-popup-lv03"
:value="coordinate"
:value="lv03Coordinate"
:coordinate-format="LV03Format"
:coordinate-projection="LV03"
>
<a :href="i18n.t('contextpopup_lv03_url')" target="_blank">
{{ LV03Format.label }}
Expand Down
55 changes: 55 additions & 0 deletions src/modules/map/components/MapPopover.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {
cssDrawingMobileToolbarHeight,
cssFooterHeight,
cssHeaderHeight,
cssTimeSliderBarHeight,
cssTimeSliderDropdownHeight,
} from '@/scss/exports'
import { useMovableElement } from '@/utils/composables/useMovableElement.composable'
import { useTippyTooltip } from '@/utils/composables/useTippyTooltip'
Expand Down Expand Up @@ -63,8 +65,10 @@ const store = useStore()
// can adapt the limits for the floating tooltip.
const isCurrentlyDrawing = computed(() => store.state.drawing.drawingOverlay.show)
const hasDevSiteWarning = computed(() => store.getters.hasDevSiteWarning)
const isTimeSliderActive = computed(() => store.state.ui.isTimeSliderActive)
const currentHeaderHeight = computed(() => store.state.ui.headerHeight)
const isPhoneMode = computed(() => store.getters.isPhoneMode)
const isDesktopMode = computed(() => store.getters.isTraditionalDesktopSize)

const cssPositionOnScreen = computed(() => {
if (mode.value === MapPopoverMode.FEATURE_TOOLTIP) {
Expand All @@ -88,6 +92,9 @@ const popoverLimits = computed(() => {
} else if (hasDevSiteWarning.value) {
top += cssDevDisclaimerHeight
}
if (isTimeSliderActive.value) {
top += isDesktopMode.value ? cssTimeSliderBarHeight : cssTimeSliderDropdownHeight
}
return {
top,
bottom: isPhoneMode.value ? 0 : cssFooterHeight,
Expand Down Expand Up @@ -125,6 +132,12 @@ function printContent() {
floating: mode === MapPopoverMode.FLOATING,
'feature-anchored': mode === MapPopoverMode.FEATURE_TOOLTIP,
'with-dev-disclaimer': hasDevSiteWarning,
'with-time-slider-bar': isTimeSliderActive && isDesktopMode,
'with-dev-disclaimer-and-time-slider-bar':
hasDevSiteWarning && isTimeSliderActive && isDesktopMode,
'with-time-slider-dropdown': isTimeSliderActive && !isDesktopMode,
'with-dev-disclaimer-and-time-slider-dropdown':
hasDevSiteWarning && isTimeSliderActive && !isDesktopMode,
'phone-mode': isPhoneMode,
'is-drawing': isCurrentlyDrawing,
}"
Expand Down Expand Up @@ -194,6 +207,26 @@ function printContent() {
&.with-dev-disclaimer {
top: calc($header-height + $dev-disclaimer-height + $screen-padding-for-ui-elements);
}
&.with-time-slider-bar {
top: calc($header-height + $time-slider-bar-height + $screen-padding-for-ui-elements);
}
&.with-time-slider-dropdown {
top: calc(
$header-height + $time-slider-dropdown-height + $screen-padding-for-ui-elements
);
}
&.with-dev-disclaimer-and-time-slider-bar {
top: calc(
$header-height + $time-slider-bar-height + $dev-disclaimer-height +
$screen-padding-for-ui-elements
);
}
&.with-dev-disclaimer-and-time-slider-dropdown {
top: calc(
$header-height + $time-slider-dropdown-height + $dev-disclaimer-height +
$screen-padding-for-ui-elements
);
}
&.phone-mode.is-drawing {
top: calc($drawing-tools-height-mobile + $screen-padding-for-ui-elements);
}
Expand Down Expand Up @@ -253,6 +286,28 @@ function printContent() {
2 * $header-height + $dev-disclaimer-height + $screen-padding-for-ui-elements
);
}
&.floating.with-time-slider-bar {
top: calc(
2 * $header-height + $time-slider-bar-height + $screen-padding-for-ui-elements
);
}
&.floating.with-time-slider-dropdown {
top: calc(
2 * $header-height + $time-slider-dropdown-height + $screen-padding-for-ui-elements
);
}
&.floating.with-dev-disclaimer-and-time-slider-bar {
top: calc(
2 * $header-height + $time-slider-bar-height + $dev-disclaimer-height +
$screen-padding-for-ui-elements
);
}
&.floating.with-dev-disclaimer-and-time-slider-dropdown {
top: calc(
2 * $header-height + $time-slider-dropdown-height + $dev-disclaimer-height +
$screen-padding-for-ui-elements
);
}
}
}
</style>
158 changes: 86 additions & 72 deletions src/modules/map/components/cesium/CesiumKMLLayer.vue
Original file line number Diff line number Diff line change
@@ -1,79 +1,93 @@
<template>
<slot />
</template>
<script setup>
import { ArcType, Color, HeightReference, KmlDataSource, LabelStyle, VerticalOrigin } from 'cesium'
import { computed, inject, onBeforeUnmount, onMounted, toRefs, watch } from 'vue'

<script>
import VectorSource from 'ol/source/Vector'
import { mapActions, mapState } from 'vuex'
import KMLLayer from '@/api/layers/KMLLayer.class.js'

import KMLLayer from '@/api/layers/KMLLayer.class'
import { parseKml } from '@/utils/kmlUtils'
const props = defineProps({
kmlLayerConfig: {
type: KMLLayer,
required: true,
},
})

import addPrimitiveFromOLLayerMixins from './utils/addPrimitiveFromOLLayer.mixins'
const { kmlLayerConfig } = toRefs(props)

const dispatcher = { dispatcher: 'CesiumKMLLayer.vue' }
const kmlData = computed(() => kmlLayerConfig.value.kmlData)

/** Renders a KML file to the Cesium viewer */
export default {
mixins: [addPrimitiveFromOLLayerMixins],
props: {
kmlLayerConfig: {
type: KMLLayer,
required: true,
},
},
computed: {
...mapState({
availableIconSets: (state) => state.drawing.iconSets,
projection: (state) => state.position.projection,
}),
opacity() {
return this.kmlLayerConfig.opacity
},
kmlData() {
return this.kmlLayerConfig.kmlData
},
iconsArePresent() {
return this.availableIconSets.length > 0
},
},
watch: {
iconsArePresent() {
this.loadDataInOLLayer().then(this.addPrimitive)
},
kmlData() {
this.loadDataInOLLayer().then(this.addPrimitive)
},
},
mounted() {
if (!this.iconsArePresent) {
this.loadAvailableIconSets(dispatcher)
}
},
methods: {
...mapActions(['loadAvailableIconSets']),
loadDataInOLLayer() {
return new Promise((resolve, reject) => {
if (!this.kmlData) {
reject(new Error('no KML data loaded yet, could not create source'))
}
if (!this.iconsArePresent) {
reject(new Error('no icons loaded yet, could not create source'))
}
this.olLayer.setSource(
new VectorSource({
wrapX: true,
projection: this.projection.epsg,
features: parseKml(
this.kmlLayerConfig,
this.projection,
this.availableIconSets
),
})
)
resolve()
})
},
},
const getViewer = inject('getViewer', () => {}, true)

onMounted(addKmlLayer)
onBeforeUnmount(removeKmlLayer)

watch(kmlData, addKmlLayer)

let kmlDataSource = null

function removeKmlLayer() {
if (kmlDataSource) {
const viewer = getViewer()
viewer.dataSources.remove(kmlDataSource)
viewer.scene.requestRender()
}
}

function addKmlLayer() {
removeKmlLayer()
if (kmlData.value) {
new KmlDataSource.load(new Blob([kmlData.value]), { clampToGround: false }).then(
(dataSource) => {
kmlDataSource = dataSource
// adding some visual improvements to KML feature, depending on their type
kmlDataSource.entities.values.forEach((entity) => {
let geometry
let alphaToApply = 0.2
let clampToGround = false
if (entity.ellipse) {
geometry = entity.ellipse
}
if (entity.polygon) {
geometry = entity.polygon
}
if (entity.polyline) {
geometry = entity.polyline
alphaToApply = 0.5
clampToGround = true
}
if (entity.billboard) {
entity.billboard.heightReference = HeightReference.CLAMP_TO_GROUND
entity.billboard.verticalOrigin = VerticalOrigin.BOTTOM
}
if (entity.label) {
const { label } = entity
label.disableDepthTestDistance = Number.POSITIVE_INFINITY
label.heightReference = HeightReference.CLAMP_TO_GROUND
label.verticalOrigin = VerticalOrigin.CENTER
label.outlineColor = Color.BLACK
label.outlineWidth = 2
label.style = LabelStyle.FILL_AND_OUTLINE
}
if (geometry) {
if (clampToGround) {
geometry.arcType = ArcType.GEODESIC
geometry.clampToGround = true
}
if (geometry.material?.color) {
geometry.material.color = geometry.material.color
.getValue()
.withAlpha(alphaToApply)
}
}
})
const viewer = getViewer()
viewer.dataSources.add(kmlDataSource)
viewer.scene.requestRender()
}
)
}
}
</script>

<template>
<slot />
</template>
Loading
Loading