mirror of
https://github.com/nasa/openmct.git
synced 2024-12-19 21:27:52 +00:00
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 <david.e.tsay@nasa.gov> Co-authored-by: David Tsay <3614296+davetsay@users.noreply.github.com>
This commit is contained in:
parent
4d84b16d8b
commit
986c596d90
@ -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
|
||||
};
|
||||
}
|
||||
|
@ -26,19 +26,18 @@
|
||||
:style="`width: 100%; height: 100%`"
|
||||
>
|
||||
<CompassHUD
|
||||
v-if="hasCameraFieldOfView"
|
||||
v-if="showCompassHUD"
|
||||
:sun-heading="sunHeading"
|
||||
:camera-angle-of-view="cameraAngleOfView"
|
||||
:camera-pan="cameraPan"
|
||||
/>
|
||||
<CompassRose
|
||||
v-if="hasCameraFieldOfView"
|
||||
:camera-angle-of-view="cameraAngleOfView"
|
||||
v-if="showCompassRose"
|
||||
:camera-pan="cameraPan"
|
||||
:compass-rose-sizing-classes="compassRoseSizingClasses"
|
||||
:heading="heading"
|
||||
:sized-image-dimensions="sizedImageDimensions"
|
||||
:sun-heading="sunHeading"
|
||||
:transformations="transformations"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@ -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: {
|
||||
|
@ -64,14 +64,14 @@
|
||||
class="c-cr__edge"
|
||||
width="100"
|
||||
height="100"
|
||||
fill="url(#paint0_radial)"
|
||||
fill="url(#gradient_edge)"
|
||||
/>
|
||||
<rect
|
||||
v-if="hasSunHeading"
|
||||
class="c-cr__sun"
|
||||
width="100"
|
||||
height="100"
|
||||
fill="url(#paint1_radial)"
|
||||
fill="url(#gradient_sun)"
|
||||
:style="sunHeadingStyle"
|
||||
/>
|
||||
|
||||
@ -107,9 +107,26 @@
|
||||
height="100"
|
||||
/>
|
||||
</mask>
|
||||
|
||||
<!-- Equipment (spacecraft) body holder. Transforms relative to the camera position. -->
|
||||
<g
|
||||
v-if="hasHeading"
|
||||
class="cr-vrover"
|
||||
:style="camAngleAndPositionStyle"
|
||||
>
|
||||
<!-- Equipment body. Rotates relative to the camera gimbal value for cams that gimbal. -->
|
||||
<path
|
||||
class="cr-vrover__body"
|
||||
:style="camGimbalAngleStyle"
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M5 0C2.23858 0 0 2.23858 0 5V95C0 97.7614 2.23858 100 5 100H95C97.7614 100 100 97.7614 100 95V5C100 2.23858 97.7614 0 95 0H5ZM85 59L50 24L15 59H33V75H67.0455V59H85Z"
|
||||
/>
|
||||
</g>
|
||||
|
||||
<g
|
||||
class="c-cr__cam-fov"
|
||||
:style="cameraPanStyle"
|
||||
:style="cameraHeadingStyle"
|
||||
>
|
||||
<g mask="url(#mask2)">
|
||||
<rect
|
||||
@ -128,19 +145,13 @@
|
||||
:style="cameraFOVStyleLeftHalf"
|
||||
/>
|
||||
</g>
|
||||
<polygon
|
||||
class="c-cr__cam"
|
||||
points="0,0 100,0 70,40 70,100 30,100 30,40"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- Spacecraft body -->
|
||||
<path
|
||||
v-if="hasHeading"
|
||||
class="c-cr__spacecraft-body"
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M37 49C35.3431 49 34 50.3431 34 52V82C34 83.6569 35.3431 85 37 85H63C64.6569 85 66 83.6569 66 82V52C66 50.3431 64.6569 49 63 49H37ZM50 52L58 60H55V67H45V60H42L50 52Z"
|
||||
:style="headingStyle"
|
||||
/>
|
||||
|
||||
<!-- NSEW and ticks -->
|
||||
<g
|
||||
class="c-cr__nsew"
|
||||
@ -193,7 +204,7 @@
|
||||
</g>
|
||||
<defs>
|
||||
<radialGradient
|
||||
id="paint0_radial"
|
||||
id="gradient_edge"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
@ -201,7 +212,7 @@
|
||||
gradientTransform="translate(50 50) rotate(90) scale(50)"
|
||||
>
|
||||
<stop
|
||||
offset="0.751387"
|
||||
offset="0.6"
|
||||
stop-opacity="0"
|
||||
/>
|
||||
<stop
|
||||
@ -210,7 +221,7 @@
|
||||
/>
|
||||
</radialGradient>
|
||||
<radialGradient
|
||||
id="paint1_radial"
|
||||
id="gradient_sun"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
@ -218,12 +229,17 @@
|
||||
gradientTransform="translate(50 -7) rotate(-90) scale(18.5)"
|
||||
>
|
||||
<stop
|
||||
offset="0.716377"
|
||||
offset="0.7"
|
||||
stop-color="#FFCC00"
|
||||
/>
|
||||
<stop
|
||||
offset="0.7"
|
||||
stop-color="#FFCC00"
|
||||
stop-opacity="0.6"
|
||||
/>
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#FF9900"
|
||||
stop-color="#FF6600"
|
||||
stop-opacity="0"
|
||||
/>
|
||||
</radialGradient>
|
||||
@ -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: {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -93,7 +93,6 @@
|
||||
></div>
|
||||
<Compass
|
||||
v-if="shouldDisplayCompass"
|
||||
:compass-rose-sizing-classes="compassRoseSizingClasses"
|
||||
:image="focusedImage"
|
||||
:natural-aspect-ratio="focusedImageNaturalAspectRatio"
|
||||
:sized-image-dimensions="sizedImageDimensions"
|
||||
@ -298,18 +297,6 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
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;
|
||||
},
|
||||
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 => {
|
||||
|
Loading…
Reference in New Issue
Block a user