import { computed, nextTick, ref } from 'vue'; import { AnchorPoint, ColourPresetData, CurrentScanState, InitialScanState, PositionData, ScanView, } from '@3cr/types-ts'; import { inflateInitialScanState, inflateScanState, } from '@/functions/modelHelper'; import { clamp } from '@/functions/clamp'; const _stlResolution = ref(5); export const currentColourPreset = ref(); export const transactionStarted = ref(false); export const scanStateIncoming = ref(''); export const initialScanState = ref( inflateInitialScanState(), ); export const scanState = ref(inflateScanState()); export const previousLayout = ref([]); export const huMinMax = ref({ min: -999999, max: 999999 }); export const tMinMax = ref({ min: 0, max: 999999 }); export const sMinMax = ref({ min: 0, max: 999999 }); export const cMinMax = ref({ min: 0, max: 999999 }); export const stlResolution = computed({ /* v8 ignore start -- @preserve */ get(): number { return _stlResolution.value; }, set(value: number): void { // STL Resolution intentionally limited between 0 and 25%. _stlResolution.value = clamp(value, 0, 25); }, /* v8 ignore stop -- @preserve */ }); export const windowSlider = computed({ get(): [number, number] { const { WindowLower, WindowUpper } = scanState.value.Display; return [WindowLower, WindowUpper]; }, set(value: [number, number]): void { scanState.value.Display.WindowLower = value[0]; scanState.value.Display.WindowUpper = value[1]; }, }); export const thresholdSlider = computed({ get(): [number, number] { const { ThresholdLower, ThresholdUpper } = scanState.value.Display; return [Math.trunc(ThresholdLower), Math.trunc(ThresholdUpper)]; }, set(value: [number, number]): void { scanState.value.Display.ThresholdLower = value[0]; scanState.value.Display.ThresholdUpper = value[1]; }, }); export const tSlider = computed({ get(): [number, number] { const { TransverseLower, TransverseUpper } = scanState.value.Slice; return [Math.trunc(TransverseLower), Math.trunc(TransverseUpper)]; }, set(value: [number, number]): void { scanState.value.Slice.TransverseLower = value[0]; scanState.value.Slice.TransverseUpper = value[1]; }, }); export const sSlider = computed({ get(): [number, number] { const { SagittalLower, SagittalUpper } = scanState.value.Slice; return [Math.trunc(SagittalLower), Math.trunc(SagittalUpper)]; }, set(value: [number, number]): void { scanState.value.Slice.SagittalLower = value[0]; scanState.value.Slice.SagittalUpper = value[1]; }, }); export const cSlider = computed({ get(): [number, number] { const { CoronalLower, CoronalUpper } = scanState.value.Slice; return [Math.trunc(CoronalLower), Math.trunc(CoronalUpper)]; }, set(value: [number, number]): void { scanState.value.Slice.CoronalLower = value[0]; scanState.value.Slice.CoronalUpper = value[1]; }, }); export const isLayout2x2 = computed(() => { return ( scanState.value.Layout.PositionData.length > 1 && scanState.value.Layout.PositionData[0].Anchor === AnchorPoint.TOP_LEFT && scanState.value.Layout.PositionData[1].Anchor === AnchorPoint.TOP_RIGHT && scanState.value.Layout.PositionData[2].Anchor === AnchorPoint.BOTTOM_LEFT && scanState.value.Layout.PositionData[3].Anchor === AnchorPoint.BOTTOM_RIGHT ); }); export const isLayout1x3 = computed(() => { return ( scanState.value.Layout.PositionData.length > 1 && scanState.value.Layout.PositionData[0].Anchor === AnchorPoint.CENTER && scanState.value.Layout.PositionData[1].Anchor === AnchorPoint.TOP_RIGHT && scanState.value.Layout.PositionData[2].Anchor === AnchorPoint.RIGHT && scanState.value.Layout.PositionData[3].Anchor === AnchorPoint.BOTTOM_RIGHT ); }); export const isFullscreen = computed(() => { return scanState.value.Layout.PositionData.length === 1; }); export const fullscreenView = computed(() => { /* v8 ignore start -- @preserve */ return isFullscreen.value ? scanState.value.CurrentView : null; /* v8 ignore stop -- @preserve */ }); export const currentGreyscalePreset = computed(() => { for (const preset of initialScanState.value.GreyscalePresets) { if ( (scanState.value.Display.WindowLower === preset.Lower || (preset.Lower < initialScanState.value.HuLower && scanState.value.Display.WindowLower === initialScanState.value.HuLower)) && (scanState.value.Display.WindowUpper === preset.Upper || (preset.Upper > initialScanState.value.HuUpper && scanState.value.Display.WindowUpper === initialScanState.value.HuUpper)) ) { return preset; } } return undefined; }); export async function setScanStateFromPayload(message: string): Promise { transactionStarted.value = true; scanStateIncoming.value = JSON.stringify(JSON.parse(message), null, 2); setScanState(message); await nextTick(); transactionStarted.value = false; } export function setInitialScanStateFromPayload(message: string): void { transactionStarted.value = true; scanStateIncoming.value = JSON.stringify(JSON.parse(message), null, 2); const obj = JSON.parse(scanStateIncoming.value) as InitialScanState; setScanState(JSON.stringify(obj.DefaultDisplaySettings, null, 2)); initialScanState.value = obj; huMinMax.value.max = obj.HuUpper; huMinMax.value.min = obj.HuLower; sMinMax.value.max = obj.XSlices; cMinMax.value.max = obj.YSlices; tMinMax.value.max = obj.ZSlices; currentColourPreset.value = obj.ColourPresets[0]; } export function setScanState(message: string): void { scanState.value = JSON.parse(message) as CurrentScanState; } export function getCurrentView(position: PositionData): ScanView { return scanState.value.Layout.PositionData.length !== 1 ? position.DefaultView : scanState.value.CurrentView; } export function isHorizontalFlip(view: ScanView): boolean { switch (view) { case ScanView.Coronal: return scanState.value.Orientations.Coronal.HorizontalFlip; case ScanView.Sagittal: return scanState.value.Orientations.Sagittal.HorizontalFlip; case ScanView.Transverse: return scanState.value.Orientations.Transverse.HorizontalFlip; default: return false; } } export function isVerticalFlip(view: ScanView): boolean { switch (view) { case ScanView.Coronal: return scanState.value.Orientations.Coronal.VerticalFlip; case ScanView.Sagittal: return scanState.value.Orientations.Sagittal.VerticalFlip; case ScanView.Transverse: return scanState.value.Orientations.Transverse.VerticalFlip; default: return false; } }