From 986c596d90da013172232ec5bccb7284d909259e Mon Sep 17 00:00:00 2001 From: Charles Hacskaylo Date: Fri, 20 Jan 2023 23:21:57 -0800 Subject: [PATCH] Imagery compass rose enhancements (#6140) * Fixes 6139 - Markup changes and improvements in CompassRose.vue. - Improved sun and edge gradients. - Related CSS styles updated. - Changed compass key color from cyan to white to avoid conflict with staleness color. * change var def to avoid collision * compass rose should size itself based on image * allow heading or camera pan for fixed cameras * suppress HUD if no camera pan * allow image to display compass rose for other cams * update example imagery to accept transformations * remove comments Co-authored-by: David Tsay Co-authored-by: David Tsay <3614296+davetsay@users.noreply.github.com> --- example/imagery/plugin.js | 8 ++ .../imagery/components/Compass/Compass.vue | 31 +++-- .../components/Compass/CompassRose.vue | 119 +++++++++++++----- .../imagery/components/Compass/compass.scss | 23 +++- .../imagery/components/ImageryView.vue | 35 +++--- 5 files changed, 152 insertions(+), 64 deletions(-) diff --git a/example/imagery/plugin.js b/example/imagery/plugin.js index 2f323356dd..e193c99afd 100644 --- a/example/imagery/plugin.js +++ b/example/imagery/plugin.js @@ -242,6 +242,13 @@ function pointForTimestamp(timestamp, name, imageSamples, delay) { const url = imageSamples[Math.floor(timestamp / delay) % imageSamples.length]; const urlItems = url.split('/'); const imageDownloadName = `example.imagery.${urlItems[urlItems.length - 1]}`; + const navCamTransformations = { + "translateX": 0, + "translateY": 18, + "rotation": 0, + "scale": 0.3, + "cameraAngleOfView": 70 + }; return { name, @@ -251,6 +258,7 @@ function pointForTimestamp(timestamp, name, imageSamples, delay) { sunOrientation: getCompassValues(0, 360), cameraPan: getCompassValues(0, 360), heading: getCompassValues(0, 360), + transformations: navCamTransformations, imageDownloadName }; } diff --git a/src/plugins/imagery/components/Compass/Compass.vue b/src/plugins/imagery/components/Compass/Compass.vue index 850cd3c7d2..15d2f65090 100644 --- a/src/plugins/imagery/components/Compass/Compass.vue +++ b/src/plugins/imagery/components/Compass/Compass.vue @@ -26,19 +26,18 @@ :style="`width: 100%; height: 100%`" > @@ -47,18 +46,12 @@ import CompassHUD from './CompassHUD.vue'; import CompassRose from './CompassRose.vue'; -const CAMERA_ANGLE_OF_VIEW = 70; - export default { components: { CompassHUD, CompassRose }, props: { - compassRoseSizingClasses: { - type: String, - required: true - }, image: { type: Object, required: true @@ -69,13 +62,19 @@ export default { } }, computed: { - hasCameraFieldOfView() { - return this.cameraPan !== undefined && this.cameraAngleOfView > 0; + showCompassHUD() { + return this.hasCameraPan && this.cameraAngleOfView > 0; + }, + showCompassRose() { + return (this.hasCameraPan || this.hasHeading) && this.cameraAngleOfView > 0; }, // horizontal rotation from north in degrees heading() { return this.image.heading; }, + hasHeading() { + return this.heading !== undefined; + }, // horizontal rotation from north in degrees sunHeading() { return this.image.sunOrientation; @@ -84,8 +83,14 @@ export default { cameraPan() { return this.image.cameraPan; }, + hasCameraPan() { + return this.cameraPan !== undefined; + }, cameraAngleOfView() { - return CAMERA_ANGLE_OF_VIEW; + return this.transformations?.cameraAngleOfView; + }, + transformations() { + return this.image.transformations; } }, methods: { diff --git a/src/plugins/imagery/components/Compass/CompassRose.vue b/src/plugins/imagery/components/Compass/CompassRose.vue index d66e382a4a..958bd3779b 100644 --- a/src/plugins/imagery/components/Compass/CompassRose.vue +++ b/src/plugins/imagery/components/Compass/CompassRose.vue @@ -64,14 +64,14 @@ class="c-cr__edge" width="100" height="100" - fill="url(#paint0_radial)" + fill="url(#gradient_edge)" /> @@ -107,9 +107,26 @@ height="100" /> + + + + + + + + - - - + @@ -238,10 +254,6 @@ import { throttle } from 'lodash'; export default { props: { - compassRoseSizingClasses: { - type: String, - required: true - }, heading: { type: Number, required: true, @@ -253,16 +265,13 @@ export default { type: Number, default: undefined }, - cameraAngleOfView: { + cameraPan: { type: Number, default: undefined }, - cameraPan: { - type: Number, - required: true, - default() { - return 0; - } + transformations: { + type: Object, + default: undefined }, sizedImageDimensions: { type: Object, @@ -275,11 +284,38 @@ export default { }; }, computed: { + cameraHeading() { + return this.cameraPan ?? this.heading; + }, + cameraAngleOfView() { + const cameraAngleOfView = this.transformations?.cameraAngleOfView; + + if (!cameraAngleOfView) { + console.warn('No Camera Angle of View provided'); + } + + return cameraAngleOfView; + }, + camAngleAndPositionStyle() { + const translateX = this.transformations?.translateX; + const translateY = this.transformations?.translateY; + const rotation = this.transformations?.rotation; + const scale = this.transformations?.scale; + + return { transform: `translate(${translateX}%, ${translateY}%) rotate(${rotation}deg) scale(${scale})` }; + }, + camGimbalAngleStyle() { + const rotation = rotate(this.north, this.heading); + + return { + transform: `rotate(${ rotation }deg)` + }; + }, compassRoseStyle() { return { transform: `rotate(${ this.north }deg)` }; }, north() { - return this.lockCompass ? rotate(-this.cameraPan) : 0; + return this.lockCompass ? rotate(-this.cameraHeading) : 0; }, cardinalTextRotateN() { return { transform: `translateY(-27%) rotate(${ -this.north }deg)` }; @@ -297,6 +333,7 @@ export default { return this.heading !== undefined; }, headingStyle() { + /* Replaced with computed camGimbalStyle, but left here just in case. */ const rotation = rotate(this.north, this.heading); return { @@ -313,8 +350,8 @@ export default { transform: `rotate(${ rotation }deg)` }; }, - cameraPanStyle() { - const rotation = rotate(this.north, this.cameraPan); + cameraHeadingStyle() { + const rotation = rotate(this.north, this.cameraHeading); return { transform: `rotate(${ rotation }deg)` @@ -333,6 +370,24 @@ export default { return { transform: `rotate(${ -this.cameraAngleOfView / 2 }deg)` }; + }, + compassRoseSizingClasses() { + let compassRoseSizingClasses = ''; + if (this.sizedImageWidth < 300) { + compassRoseSizingClasses = '--rose-small --rose-min'; + } else if (this.sizedImageWidth < 500) { + compassRoseSizingClasses = '--rose-small'; + } else if (this.sizedImageWidth > 1000) { + compassRoseSizingClasses = '--rose-max'; + } + + return compassRoseSizingClasses; + }, + sizedImageWidth() { + return this.sizedImageDimensions.width; + }, + sizedImageHeight() { + return this.sizedImageDimensions.height; } }, watch: { diff --git a/src/plugins/imagery/components/Compass/compass.scss b/src/plugins/imagery/components/Compass/compass.scss index 5609bf9f60..a143706b2b 100644 --- a/src/plugins/imagery/components/Compass/compass.scss +++ b/src/plugins/imagery/components/Compass/compass.scss @@ -1,5 +1,5 @@ /***************************** THEME/UI CONSTANTS AND MIXINS */ -$interfaceKeyColor: #00B9C5; +$interfaceKeyColor: #fff; $elemBg: rgba(black, 0.7); @mixin sun($position: 'circle closest-side') { @@ -100,13 +100,19 @@ $elemBg: rgba(black, 0.7); } &__edge { - opacity: 0.1; + opacity: 0.2; } &__sun { opacity: 0.7; } + &__cam { + fill: $interfaceKeyColor; + transform-origin: center; + transform: scale(0.15); + } + &__cam-fov-l, &__cam-fov-r { // Cam FOV indication @@ -115,7 +121,6 @@ $elemBg: rgba(black, 0.7); } &__nsew-text, - &__spacecraft-body, &__ticks-major, &__ticks-minor { fill: $color; @@ -166,3 +171,15 @@ $elemBg: rgba(black, 0.7); padding-top: $s; } } + +/************************** ROVER */ +.cr-vrover { + $scale: 0.4; + transform-origin: center; + + &__body { + fill: $interfaceKeyColor; + opacity: 0.3; + transform-origin: center 7% !important; // Places rotation center at mast position + } +} diff --git a/src/plugins/imagery/components/ImageryView.vue b/src/plugins/imagery/components/ImageryView.vue index db13f8f3f5..5b18cd29d7 100644 --- a/src/plugins/imagery/components/ImageryView.vue +++ b/src/plugins/imagery/components/ImageryView.vue @@ -93,7 +93,6 @@ > 1000) { - compassRoseSizingClasses = '--rose-max'; - } - - return compassRoseSizingClasses; - }, displayThumbnails() { return ( this.forceShowThumbnails @@ -432,7 +419,6 @@ export default { shouldDisplayCompass() { const imageHeightAndWidth = this.sizedImageHeight !== 0 && this.sizedImageWidth !== 0; - const display = this.focusedImage !== undefined && this.focusedImageNaturalAspectRatio !== undefined && this.imageContainerWidth !== undefined @@ -440,8 +426,9 @@ export default { && imageHeightAndWidth && this.zoomFactor === 1 && this.imagePanned !== true; + const hasCameraConfigurations = this.focusedImage?.transformations !== undefined; - return display; + return display && hasCameraConfigurations; }, isSpacecraftPositionFresh() { let isFresh = undefined; @@ -626,6 +613,7 @@ export default { this.spacecraftOrientationKeys = ['heading']; this.cameraKeys = ['cameraPan', 'cameraTilt']; this.sunKeys = ['sunOrientation']; + this.transformationsKeys = ['transformations']; // related telemetry await this.initializeRelatedTelemetry(); @@ -728,7 +716,13 @@ export default { this.relatedTelemetry = new RelatedTelemetry( this.openmct, this.domainObject, - [...this.spacecraftPositionKeys, ...this.spacecraftOrientationKeys, ...this.cameraKeys, ...this.sunKeys] + [ + ...this.spacecraftPositionKeys, + ...this.spacecraftOrientationKeys, + ...this.cameraKeys, + ...this.sunKeys, + ...this.transformationsKeys + ] ); if (this.relatedTelemetry.hasRelatedTelemetry) { @@ -837,6 +831,15 @@ export default { this.$set(this.focusedImageRelatedTelemetry, key, value); } } + + // set configuration for compass + this.transformationsKeys.forEach(key => { + const transformations = this.relatedTelemetry[key]; + + if (transformations !== undefined) { + this.$set(this.imageHistory[this.focusedImageIndex], key, transformations); + } + }); }, trackLatestRelatedTelemetry() { [...this.spacecraftPositionKeys, ...this.spacecraftOrientationKeys, ...this.cameraKeys, ...this.sunKeys].forEach(key => {