dicom阅片比例尺修改
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
8590808cb9
commit
a7b9218952
|
|
@ -661,6 +661,7 @@ export default {
|
||||||
},
|
},
|
||||||
sliderMouseup(e) {
|
sliderMouseup(e) {
|
||||||
this.sliderInfo.isMove = false
|
this.sliderInfo.isMove = false
|
||||||
|
this.$emit('contentMouseup', e)
|
||||||
},
|
},
|
||||||
sliderMousedown(e) {
|
sliderMousedown(e) {
|
||||||
const boxHeight = this.$refs['sliderBox'].clientHeight
|
const boxHeight = this.$refs['sliderBox'].clientHeight
|
||||||
|
|
|
||||||
|
|
@ -295,7 +295,7 @@
|
||||||
<Viewport :ref="`viewport-${index}`" :data-viewport-uid="`viewport-${index}`"
|
<Viewport :ref="`viewport-${index}`" :data-viewport-uid="`viewport-${index}`"
|
||||||
:rendering-engine-id="renderingEngineId" :viewport-id="`viewport-${index}`" :viewport-index="index"
|
:rendering-engine-id="renderingEngineId" :viewport-id="`viewport-${index}`" :viewport-index="index"
|
||||||
@activeViewport="activeViewport" @toggleTaskByViewport="toggleTaskByViewport" @previewCD="previewCD"
|
@activeViewport="activeViewport" @toggleTaskByViewport="toggleTaskByViewport" @previewCD="previewCD"
|
||||||
@renderAnnotations="renderAnnotations" />
|
@renderAnnotations="renderAnnotations" @contentMouseup="contentMouseup" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="readingTool === 2" :class="['viewports-box', !isFusion ? 'viewports-box-down' : '']"
|
<div v-if="readingTool === 2" :class="['viewports-box', !isFusion ? 'viewports-box-down' : '']"
|
||||||
|
|
@ -308,7 +308,8 @@
|
||||||
:rendering-engine-id="renderingEngineId" :viewport-id="`viewport-fusion-${index}`"
|
:rendering-engine-id="renderingEngineId" :viewport-id="`viewport-fusion-${index}`"
|
||||||
:viewport-index="index" @activeViewport="activeViewport"
|
:viewport-index="index" @activeViewport="activeViewport"
|
||||||
@toggleTaskByViewport="toggleTaskByViewport" @previewCD="previewCD"
|
@toggleTaskByViewport="toggleTaskByViewport" @previewCD="previewCD"
|
||||||
@renderAnnotations="renderAnnotations" @upperRangeChange="upperRangeChange" />
|
@renderAnnotations="renderAnnotations" @upperRangeChange="upperRangeChange"
|
||||||
|
@contentMouseup="contentMouseup" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -361,7 +362,8 @@
|
||||||
<!-- 手册 -->
|
<!-- 手册 -->
|
||||||
<span>{{ $t('trials:reading:button:handbooks') }}</span>
|
<span>{{ $t('trials:reading:button:handbooks') }}</span>
|
||||||
<span style="position: absolute;right: 20px;font-size: 20px;">
|
<span style="position: absolute;right: 20px;font-size: 20px;">
|
||||||
<svg-icon :icon-class="isFullscreen ? 'exit-fullscreen' : 'fullscreen'" style="margin-right:10px;cursor: pointer;"
|
<svg-icon :icon-class="isFullscreen ? 'exit-fullscreen' : 'fullscreen'"
|
||||||
|
style="margin-right:10px;cursor: pointer;"
|
||||||
@click="manualsDialog.isFullscreen = !manualsDialog.isFullscreen" />
|
@click="manualsDialog.isFullscreen = !manualsDialog.isFullscreen" />
|
||||||
<svg-icon icon-class="close" style="cursor: pointer;" @click="manualsDialog.visible = false" />
|
<svg-icon icon-class="close" style="cursor: pointer;" @click="manualsDialog.visible = false" />
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -460,6 +462,7 @@ import ClinicalData from '@/views/trials/trials-panel/reading/clinical-data'
|
||||||
import FusionForm from './FusionForm.vue'
|
import FusionForm from './FusionForm.vue'
|
||||||
import colorMap from './colorMap.vue'
|
import colorMap from './colorMap.vue'
|
||||||
import RectangleROITool from './tools/RectangleROITool'
|
import RectangleROITool from './tools/RectangleROITool'
|
||||||
|
import ScaleOverlayTool from './tools/ScaleOverlayTool'
|
||||||
import uploadDicomAndNonedicom from '@/components/uploadDicomAndNonedicom'
|
import uploadDicomAndNonedicom from '@/components/uploadDicomAndNonedicom'
|
||||||
import downloadDicomAndNonedicom from '@/components/downloadDicomAndNonedicom'
|
import downloadDicomAndNonedicom from '@/components/downloadDicomAndNonedicom'
|
||||||
import { getNetWorkSpeed, setNetWorkSpeedSizeAll, workSpeedclose } from "@/utils"
|
import { getNetWorkSpeed, setNetWorkSpeedSizeAll, workSpeedclose } from "@/utils"
|
||||||
|
|
@ -470,7 +473,7 @@ const {
|
||||||
ToolGroupManager,
|
ToolGroupManager,
|
||||||
Enums: csToolsEnums,
|
Enums: csToolsEnums,
|
||||||
StackScrollTool,
|
StackScrollTool,
|
||||||
ScaleOverlayTool,
|
// ScaleOverlayTool,
|
||||||
PanTool,
|
PanTool,
|
||||||
ZoomTool,
|
ZoomTool,
|
||||||
WindowLevelTool,
|
WindowLevelTool,
|
||||||
|
|
@ -625,7 +628,12 @@ export default {
|
||||||
uploadStatus: 'upload',
|
uploadStatus: 'upload',
|
||||||
taskId: '',
|
taskId: '',
|
||||||
isReadingTaskViewInOrder: null,
|
isReadingTaskViewInOrder: null,
|
||||||
trialCriterion: {}
|
trialCriterion: {},
|
||||||
|
|
||||||
|
curOperation: {
|
||||||
|
type: '',
|
||||||
|
annotation: null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -1479,11 +1487,8 @@ export default {
|
||||||
if (isBound || this.isNumber(operateStateEnum)) {
|
if (isBound || this.isNumber(operateStateEnum)) {
|
||||||
this.$refs[`ecrf_${series.TaskInfo.VisitTaskId}`][0].updateAnnotationToQuestion(annotation)
|
this.$refs[`ecrf_${series.TaskInfo.VisitTaskId}`][0].updateAnnotationToQuestion(annotation)
|
||||||
} else {
|
} else {
|
||||||
if (this.saveCustomAnnotationTimer) {
|
this.curOperation.type = 'Modified'
|
||||||
clearTimeout(this.saveCustomAnnotationTimer)
|
this.curOperation.annotation = annotation
|
||||||
this.saveCustomAnnotationTimer = null
|
|
||||||
}
|
|
||||||
this.saveCustomAnnotationTimer = setTimeout(() => { this.saveCustomAnnotation(annotation) }, 1000)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.setToolsPassive()
|
this.setToolsPassive()
|
||||||
|
|
@ -1553,6 +1558,17 @@ export default {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
contentMouseup(e) {
|
||||||
|
console.log('contentMouseup')
|
||||||
|
if (this.curOperation.type === 'Modified') {
|
||||||
|
let annotation = this.curOperation.annotation
|
||||||
|
this.saveCustomAnnotation(annotation)
|
||||||
|
}
|
||||||
|
this.curOperation = {
|
||||||
|
type: '',
|
||||||
|
annotation: null
|
||||||
|
}
|
||||||
|
},
|
||||||
removeAnnotation(annotation) {
|
removeAnnotation(annotation) {
|
||||||
cornerstoneTools.annotation.state.removeAnnotation(annotation.annotationUID)
|
cornerstoneTools.annotation.state.removeAnnotation(annotation.annotationUID)
|
||||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||||
|
|
@ -3032,21 +3048,25 @@ export default {
|
||||||
let volumeId = null; let volume = null
|
let volumeId = null; let volume = null
|
||||||
const key = isFusion ? `fusion_${serie.SeriesInstanceUid}` : serie.SeriesInstanceUid
|
const key = isFusion ? `fusion_${serie.SeriesInstanceUid}` : serie.SeriesInstanceUid
|
||||||
if (!this.volumeData[key] || !cache.getVolume(this.volumeData[key].volumeId)) {
|
if (!this.volumeData[key] || !cache.getVolume(this.volumeData[key].volumeId)) {
|
||||||
if (serie.Modality === 'PT' && !isFusion) {
|
// if (serie.Modality === 'PT' && !isFusion) {
|
||||||
serie.ImageIds.forEach(async id => {
|
// serie.ImageIds.forEach(async id => {
|
||||||
const imageLoadObject = cache.getImage(id)
|
// const imageLoadObject = cache.getImage(id)
|
||||||
if (imageLoadObject) {
|
// if (imageLoadObject) {
|
||||||
await new Promise(res => {
|
// await new Promise(res => {
|
||||||
cache.removeImageLoadObject(id, { force: true }) // 从缓存中删除
|
// cache.removeImageLoadObject(id, { force: true }) // 从缓存中删除
|
||||||
res()
|
// res()
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
|
// }
|
||||||
|
volumeId = `${isFusion ? 'fusion' : serie.Modality}Volume` + ':' + serie.SeriesInstanceUid
|
||||||
|
if (cache.getVolume(volumeId)) {
|
||||||
|
volume = cache.getVolume(volumeId)
|
||||||
|
} else {
|
||||||
|
await this.$refs[`viewport-fusion-0`][0].createImageIdsAndCacheMetaData(serie)
|
||||||
|
volume = await volumeLoader.createAndCacheVolume(volumeId, { imageIds: serie.ImageIds })
|
||||||
|
volume.load()
|
||||||
}
|
}
|
||||||
await this.$refs[`viewport-fusion-0`][0].createImageIdsAndCacheMetaData(serie)
|
|
||||||
volumeId = `${isFusion ? 'fusion' : serie.Modality}Volume` + ':' + csUtils.uuidv4()
|
|
||||||
volume = await volumeLoader.createAndCacheVolume(volumeId, { imageIds: serie.ImageIds })
|
|
||||||
volume.load()
|
|
||||||
this.volumeData[key] = {}
|
this.volumeData[key] = {}
|
||||||
this.volumeData[key].volumeId = volumeId
|
this.volumeData[key].volumeId = volumeId
|
||||||
this.volumeData[key].volume = volume
|
this.volumeData[key].volume = volume
|
||||||
|
|
|
||||||
|
|
@ -481,6 +481,7 @@ export default {
|
||||||
},
|
},
|
||||||
sliderMouseup(e) {
|
sliderMouseup(e) {
|
||||||
this.sliderInfo.isMove = false
|
this.sliderInfo.isMove = false
|
||||||
|
this.$emit('contentMouseup', e)
|
||||||
},
|
},
|
||||||
sliderMousedown(e) {
|
sliderMousedown(e) {
|
||||||
const boxHeight = this.$refs['sliderBox'].clientHeight
|
const boxHeight = this.$refs['sliderBox'].clientHeight
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,409 @@
|
||||||
|
// import AnnotationDisplayTool from './base/AnnotationDisplayTool';
|
||||||
|
import { vec3 } from 'gl-matrix';
|
||||||
|
import { getEnabledElementByIds, getRenderingEngines, utilities as csUtils, } from '@cornerstonejs/core';
|
||||||
|
// import { addAnnotation, getAnnotations, } from '../stateManagement/annotation/annotationState';
|
||||||
|
// import { drawLine as drawLineSvg, drawTextBox as drawTextBoxSvg, } from '../drawingSvg';
|
||||||
|
// import { getToolGroup } from '../store/ToolGroupManager';
|
||||||
|
import * as cornerstoneTools from '@cornerstonejs/tools'
|
||||||
|
const {
|
||||||
|
annotation,
|
||||||
|
drawing,
|
||||||
|
AnnotationDisplayTool,
|
||||||
|
ToolGroupManager,
|
||||||
|
} = cornerstoneTools
|
||||||
|
const { getAnnotations, addAnnotation } = annotation.state
|
||||||
|
const { getToolGroup } = ToolGroupManager
|
||||||
|
const { drawLine, drawTextBox } = drawing
|
||||||
|
const drawLineSvg = drawLine
|
||||||
|
const drawTextBoxSvg = drawTextBox
|
||||||
|
const viewportsWithAnnotations = [];
|
||||||
|
class ScaleOverlayTool extends AnnotationDisplayTool {
|
||||||
|
constructor(toolProps = {}, defaultToolProps = {
|
||||||
|
configuration: {
|
||||||
|
viewportId: '',
|
||||||
|
scaleLocation: 'bottom',
|
||||||
|
},
|
||||||
|
}) {
|
||||||
|
super(toolProps, defaultToolProps);
|
||||||
|
this.editData = null;
|
||||||
|
this._init = () => {
|
||||||
|
const renderingEngines = getRenderingEngines();
|
||||||
|
const renderingEngine = renderingEngines[0];
|
||||||
|
if (!renderingEngine) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const viewportIds = getToolGroup(this.toolGroupId).viewportsInfo;
|
||||||
|
if (!viewportIds) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const enabledElements = viewportIds.map((e) => getEnabledElementByIds(e.viewportId, e.renderingEngineId));
|
||||||
|
let { viewport } = enabledElements[0];
|
||||||
|
const { FrameOfReferenceUID } = enabledElements[0];
|
||||||
|
if (this.configuration.viewportId) {
|
||||||
|
enabledElements.forEach((element) => {
|
||||||
|
if (element.viewport.id == this.configuration.viewportId) {
|
||||||
|
viewport = element.viewport;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!viewport) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { viewUp, viewPlaneNormal } = viewport.getCamera();
|
||||||
|
const viewportCanvasCornersInWorld = csUtils.getViewportImageCornersInWorld(viewport);
|
||||||
|
let annotation = this.editData?.annotation;
|
||||||
|
const annotations = getAnnotations(this.getToolName(), viewport.element);
|
||||||
|
if (annotations.length) {
|
||||||
|
annotation = annotations.filter((thisAnnotation) => thisAnnotation.data.viewportId == viewport.id)[0];
|
||||||
|
}
|
||||||
|
enabledElements.forEach((element) => {
|
||||||
|
const { viewport } = element;
|
||||||
|
if (!viewportsWithAnnotations.includes(viewport.id) || annotations.length === 0) {
|
||||||
|
const newAnnotation = {
|
||||||
|
metadata: {
|
||||||
|
toolName: this.getToolName(),
|
||||||
|
viewPlaneNormal: [...viewPlaneNormal],
|
||||||
|
viewUp: [...viewUp],
|
||||||
|
FrameOfReferenceUID,
|
||||||
|
referencedImageId: null,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
handles: {
|
||||||
|
points: csUtils.getViewportImageCornersInWorld(viewport),
|
||||||
|
},
|
||||||
|
viewportId: viewport.id,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
viewportsWithAnnotations.push(viewport.id);
|
||||||
|
addAnnotation(newAnnotation, viewport.element);
|
||||||
|
annotation = newAnnotation;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (this.editData?.annotation &&
|
||||||
|
this.editData.annotation.data.viewportId == viewport.id) {
|
||||||
|
this.editData.annotation.data.handles.points =
|
||||||
|
viewportCanvasCornersInWorld;
|
||||||
|
this.editData.annotation.data.viewportId = viewport.id;
|
||||||
|
}
|
||||||
|
this.editData = {
|
||||||
|
viewport,
|
||||||
|
renderingEngine,
|
||||||
|
annotation,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
this.onSetToolEnabled = () => {
|
||||||
|
this._init();
|
||||||
|
};
|
||||||
|
this.onCameraModified = (evt) => {
|
||||||
|
this.configuration.viewportId = evt.detail.viewportId;
|
||||||
|
this._init();
|
||||||
|
};
|
||||||
|
this.computeScaleSize = (worldWidthViewport, worldHeightViewport, location) => {
|
||||||
|
const scaleSizes = [
|
||||||
|
16000, 8000, 4000, 2000, 1000, 500, 250, 100, 50, 25, 10, 5, 2,
|
||||||
|
];
|
||||||
|
let currentScaleSize;
|
||||||
|
if (location == 'top' || location == 'bottom') {
|
||||||
|
currentScaleSize = scaleSizes.filter((scaleSize) => scaleSize < worldWidthViewport * 0.6 &&
|
||||||
|
scaleSize > worldWidthViewport * 0.2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
currentScaleSize = scaleSizes.filter((scaleSize) => scaleSize < worldHeightViewport * 0.6 &&
|
||||||
|
scaleSize > worldHeightViewport * 0.2);
|
||||||
|
}
|
||||||
|
return currentScaleSize[0];
|
||||||
|
};
|
||||||
|
this.computeEndScaleTicks = (canvasCoordinates, location) => {
|
||||||
|
const locationTickOffset = {
|
||||||
|
bottom: [
|
||||||
|
[0, -10],
|
||||||
|
[0, -10],
|
||||||
|
],
|
||||||
|
top: [
|
||||||
|
[0, 10],
|
||||||
|
[0, 10],
|
||||||
|
],
|
||||||
|
left: [
|
||||||
|
[0, 0],
|
||||||
|
[10, 0],
|
||||||
|
],
|
||||||
|
right: [
|
||||||
|
[0, 0],
|
||||||
|
[-10, 0],
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const endTick1 = [
|
||||||
|
[
|
||||||
|
canvasCoordinates[1][0] + locationTickOffset[location][0][0],
|
||||||
|
canvasCoordinates[1][1] + locationTickOffset[location][0][0],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
canvasCoordinates[1][0] + locationTickOffset[location][1][0],
|
||||||
|
canvasCoordinates[1][1] + locationTickOffset[location][1][1],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
const endTick2 = [
|
||||||
|
[
|
||||||
|
canvasCoordinates[0][0] + locationTickOffset[location][0][0],
|
||||||
|
canvasCoordinates[0][1] + locationTickOffset[location][0][0],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
canvasCoordinates[0][0] + locationTickOffset[location][1][0],
|
||||||
|
canvasCoordinates[0][1] + locationTickOffset[location][1][1],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
return {
|
||||||
|
endTick1: endTick1,
|
||||||
|
endTick2: endTick2,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
this.computeInnerScaleTicks = (scaleSize, location, annotationUID, leftTick, rightTick) => {
|
||||||
|
let canvasScaleSize;
|
||||||
|
if (location == 'bottom' || location == 'top') {
|
||||||
|
canvasScaleSize = rightTick[0][0] - leftTick[0][0];
|
||||||
|
}
|
||||||
|
else if (location == 'left' || location == 'right') {
|
||||||
|
canvasScaleSize = rightTick[0][1] - leftTick[0][1];
|
||||||
|
}
|
||||||
|
const tickIds = [];
|
||||||
|
const tickUIDs = [];
|
||||||
|
const tickCoordinates = [];
|
||||||
|
let numberSmallTicks = scaleSize;
|
||||||
|
if (scaleSize >= 50) {
|
||||||
|
numberSmallTicks = scaleSize / 10;
|
||||||
|
}
|
||||||
|
const tickSpacing = canvasScaleSize / numberSmallTicks;
|
||||||
|
for (let i = 0; i < numberSmallTicks - 1; i++) {
|
||||||
|
const locationOffset = {
|
||||||
|
bottom: [
|
||||||
|
[tickSpacing * (i + 1), 0],
|
||||||
|
[tickSpacing * (i + 1), 5],
|
||||||
|
],
|
||||||
|
top: [
|
||||||
|
[tickSpacing * (i + 1), 0],
|
||||||
|
[tickSpacing * (i + 1), -5],
|
||||||
|
],
|
||||||
|
left: [
|
||||||
|
[0, tickSpacing * (i + 1)],
|
||||||
|
[-5, tickSpacing * (i + 1)],
|
||||||
|
],
|
||||||
|
right: [
|
||||||
|
[0, tickSpacing * (i + 1)],
|
||||||
|
[5, tickSpacing * (i + 1)],
|
||||||
|
],
|
||||||
|
};
|
||||||
|
tickIds.push(`${annotationUID}-tick${i}`);
|
||||||
|
tickUIDs.push(`tick${i}`);
|
||||||
|
if ((i + 1) % 5 == 0) {
|
||||||
|
tickCoordinates.push([
|
||||||
|
[
|
||||||
|
leftTick[0][0] + locationOffset[location][0][0],
|
||||||
|
leftTick[0][1] + locationOffset[location][0][1],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
leftTick[1][0] + locationOffset[location][0][0],
|
||||||
|
leftTick[1][1] + locationOffset[location][0][1],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tickCoordinates.push([
|
||||||
|
[
|
||||||
|
leftTick[0][0] + locationOffset[location][0][0],
|
||||||
|
leftTick[0][1] + locationOffset[location][0][1],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
leftTick[1][0] + locationOffset[location][1][0],
|
||||||
|
leftTick[1][1] + locationOffset[location][1][1],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { tickIds, tickUIDs, tickCoordinates };
|
||||||
|
};
|
||||||
|
this.computeWorldScaleCoordinates = (scaleSize, location, pointSet) => {
|
||||||
|
let worldCoordinates;
|
||||||
|
let topBottomVec = vec3.subtract(vec3.create(), pointSet[0], pointSet[1]);
|
||||||
|
topBottomVec = vec3.normalize(vec3.create(), topBottomVec);
|
||||||
|
let topRightVec = vec3.subtract(vec3.create(), pointSet[2], pointSet[0]);
|
||||||
|
topRightVec = vec3.normalize(vec3.create(), topRightVec);
|
||||||
|
const midpointLocation = {
|
||||||
|
bottom: [pointSet[1], pointSet[2]],
|
||||||
|
top: [pointSet[0], pointSet[3]],
|
||||||
|
right: [pointSet[2], pointSet[3]],
|
||||||
|
left: [pointSet[0], pointSet[1]],
|
||||||
|
};
|
||||||
|
const midpoint = vec3
|
||||||
|
.add(vec3.create(), midpointLocation[location][0], midpointLocation[location][0])
|
||||||
|
.map((i) => i / 2);
|
||||||
|
const offset = scaleSize /
|
||||||
|
2 /
|
||||||
|
Math.sqrt(Math.pow(topBottomVec[0], 2) +
|
||||||
|
Math.pow(topBottomVec[1], 2) +
|
||||||
|
Math.pow(topBottomVec[2], 2));
|
||||||
|
if (location == 'top' || location == 'bottom') {
|
||||||
|
worldCoordinates = [
|
||||||
|
vec3.subtract(vec3.create(), midpoint, topRightVec.map((i) => i * offset)),
|
||||||
|
vec3.add(vec3.create(), midpoint, topRightVec.map((i) => i * offset)),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
else if (location == 'left' || location == 'right') {
|
||||||
|
worldCoordinates = [
|
||||||
|
vec3.add(vec3.create(), midpoint, topBottomVec.map((i) => i * offset)),
|
||||||
|
vec3.subtract(vec3.create(), midpoint, topBottomVec.map((i) => i * offset)),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return worldCoordinates;
|
||||||
|
};
|
||||||
|
this.computeCanvasScaleCoordinates = (canvasSize, canvasCoordinates, vscaleBounds, hscaleBounds, location) => {
|
||||||
|
let scaleCanvasCoordinates;
|
||||||
|
if (location == 'top' || location == 'bottom') {
|
||||||
|
const worldDistanceOnCanvas = canvasCoordinates[0][0] - canvasCoordinates[1][0];
|
||||||
|
scaleCanvasCoordinates = [
|
||||||
|
[canvasSize.width / 2 - worldDistanceOnCanvas / 2, vscaleBounds.height],
|
||||||
|
[canvasSize.width / 2 + worldDistanceOnCanvas / 2, vscaleBounds.height],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
else if (location == 'left' || location == 'right') {
|
||||||
|
const worldDistanceOnCanvas = canvasCoordinates[0][1] - canvasCoordinates[1][1];
|
||||||
|
scaleCanvasCoordinates = [
|
||||||
|
[hscaleBounds.width, canvasSize.height / 2 - worldDistanceOnCanvas / 2],
|
||||||
|
[hscaleBounds.width, canvasSize.height / 2 + worldDistanceOnCanvas / 2],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return scaleCanvasCoordinates;
|
||||||
|
};
|
||||||
|
this.computeScaleBounds = (canvasSize, horizontalReduction, verticalReduction, location) => {
|
||||||
|
const hReduction = horizontalReduction * Math.min(1000, canvasSize.width);
|
||||||
|
const vReduction = verticalReduction * Math.min(1000, canvasSize.height);
|
||||||
|
const locationBounds = {
|
||||||
|
bottom: [-vReduction, -hReduction],
|
||||||
|
top: [vReduction, hReduction],
|
||||||
|
left: [vReduction, hReduction],
|
||||||
|
right: [-vReduction, -hReduction],
|
||||||
|
};
|
||||||
|
const canvasBounds = {
|
||||||
|
bottom: [canvasSize.height, canvasSize.width],
|
||||||
|
top: [0, canvasSize.width],
|
||||||
|
left: [canvasSize.height, 0],
|
||||||
|
right: [canvasSize.height, canvasSize.width],
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
height: canvasBounds[location][0] + locationBounds[location][0],
|
||||||
|
width: canvasBounds[location][1] + locationBounds[location][1],
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
renderAnnotation(enabledElement, svgDrawingHelper) {
|
||||||
|
if (!this.editData || !this.editData.viewport) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const location = this.configuration.scaleLocation;
|
||||||
|
const { viewport } = enabledElement;
|
||||||
|
const annotations = getAnnotations(this.getToolName(), viewport.element);
|
||||||
|
const annotation = annotations.filter((thisAnnotation) => thisAnnotation.data.viewportId == viewport.id)[0];
|
||||||
|
const canvas = enabledElement.viewport.canvas;
|
||||||
|
const renderStatus = false;
|
||||||
|
if (!viewport) {
|
||||||
|
return renderStatus;
|
||||||
|
}
|
||||||
|
const styleSpecifier = {
|
||||||
|
toolGroupId: this.toolGroupId,
|
||||||
|
toolName: this.getToolName(),
|
||||||
|
viewportId: enabledElement.viewport.id,
|
||||||
|
};
|
||||||
|
const canvasSize = {
|
||||||
|
width: canvas.width / window.devicePixelRatio || 1,
|
||||||
|
height: canvas.height / window.devicePixelRatio || 1,
|
||||||
|
};
|
||||||
|
const topLeft = annotation.data.handles.points[0];
|
||||||
|
const topRight = annotation.data.handles.points[1];
|
||||||
|
const bottomLeft = annotation.data.handles.points[2];
|
||||||
|
const bottomRight = annotation.data.handles.points[3];
|
||||||
|
const pointSet1 = [topLeft, bottomLeft, topRight, bottomRight];
|
||||||
|
const worldWidthViewport = vec3.distance(bottomLeft, bottomRight);
|
||||||
|
const worldHeightViewport = vec3.distance(topLeft, bottomLeft);
|
||||||
|
const hscaleBounds = this.computeScaleBounds(canvasSize, 0.05, 0.05, location);
|
||||||
|
const vscaleBounds = this.computeScaleBounds(canvasSize, 0.05, 0.05, location);
|
||||||
|
const scaleSize = this.computeScaleSize(worldWidthViewport, worldHeightViewport, location);
|
||||||
|
const canvasCoordinates = this.computeWorldScaleCoordinates(scaleSize, location, pointSet1).map((world) => viewport.worldToCanvas(world));
|
||||||
|
const scaleCanvasCoordinates = this.computeCanvasScaleCoordinates(canvasSize, canvasCoordinates, vscaleBounds, hscaleBounds, location);
|
||||||
|
const scaleTicks = this.computeEndScaleTicks(scaleCanvasCoordinates, location);
|
||||||
|
const { annotationUID } = annotation;
|
||||||
|
styleSpecifier.annotationUID = annotationUID;
|
||||||
|
const lineWidth = this.getStyle('lineWidth', styleSpecifier, annotation);
|
||||||
|
const lineDash = this.getStyle('lineDash', styleSpecifier, annotation);
|
||||||
|
const color = this.getStyle('color', styleSpecifier, annotation);
|
||||||
|
const shadow = this.getStyle('shadow', styleSpecifier, annotation);
|
||||||
|
const scaleId = `${annotationUID}-scaleline`;
|
||||||
|
const scaleLineUID = '1';
|
||||||
|
drawLineSvg(svgDrawingHelper, annotationUID, scaleLineUID, scaleCanvasCoordinates[0], scaleCanvasCoordinates[1], {
|
||||||
|
color,
|
||||||
|
width: lineWidth,
|
||||||
|
lineDash,
|
||||||
|
shadow,
|
||||||
|
}, scaleId);
|
||||||
|
const leftTickId = `${annotationUID}-left`;
|
||||||
|
const leftTickUID = '2';
|
||||||
|
drawLineSvg(svgDrawingHelper, annotationUID, leftTickUID, scaleTicks.endTick1[0], scaleTicks.endTick1[1], {
|
||||||
|
color,
|
||||||
|
width: lineWidth,
|
||||||
|
lineDash,
|
||||||
|
shadow,
|
||||||
|
}, leftTickId);
|
||||||
|
const rightTickId = `${annotationUID}-right`;
|
||||||
|
const rightTickUID = '3';
|
||||||
|
drawLineSvg(svgDrawingHelper, annotationUID, rightTickUID, scaleTicks.endTick2[0], scaleTicks.endTick2[1], {
|
||||||
|
color,
|
||||||
|
width: lineWidth,
|
||||||
|
lineDash,
|
||||||
|
shadow,
|
||||||
|
}, rightTickId);
|
||||||
|
const locationTextOffest = {
|
||||||
|
bottom: [-10, -42],
|
||||||
|
top: [-12, -35],
|
||||||
|
left: [-40, -20],
|
||||||
|
right: [-50, -20],
|
||||||
|
};
|
||||||
|
const textCanvasCoordinates = [
|
||||||
|
scaleCanvasCoordinates[0][0] + locationTextOffest[location][0],
|
||||||
|
scaleCanvasCoordinates[0][1] + locationTextOffest[location][1],
|
||||||
|
];
|
||||||
|
const textBoxLines = this._getTextLines(scaleSize);
|
||||||
|
const { tickIds, tickUIDs, tickCoordinates } = this.computeInnerScaleTicks(scaleSize, location, annotationUID, scaleTicks.endTick1, scaleTicks.endTick2);
|
||||||
|
for (let i = 0; i < tickUIDs.length; i++) {
|
||||||
|
drawLineSvg(svgDrawingHelper, annotationUID, tickUIDs[i], tickCoordinates[i][0], tickCoordinates[i][1], {
|
||||||
|
color,
|
||||||
|
width: lineWidth,
|
||||||
|
lineDash,
|
||||||
|
shadow,
|
||||||
|
}, tickIds[i]);
|
||||||
|
}
|
||||||
|
const textUID = 'text0';
|
||||||
|
drawTextBoxSvg(svgDrawingHelper, annotationUID, textUID, textBoxLines, [textCanvasCoordinates[0], textCanvasCoordinates[1]], {
|
||||||
|
fontFamily: 'Helvetica Neue, Helvetica, Arial, sans-serif',
|
||||||
|
fontSize: '14px',
|
||||||
|
lineDash: '2,3',
|
||||||
|
lineWidth: '1',
|
||||||
|
shadow: true,
|
||||||
|
color: color,
|
||||||
|
});
|
||||||
|
return renderStatus;
|
||||||
|
}
|
||||||
|
_getTextLines(scaleSize) {
|
||||||
|
let scaleSizeDisplayValue;
|
||||||
|
let scaleSizeUnits;
|
||||||
|
if (scaleSize >= 50) {
|
||||||
|
scaleSizeDisplayValue = scaleSize / 10;
|
||||||
|
scaleSizeUnits = ' cm';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
scaleSizeDisplayValue = scaleSize;
|
||||||
|
scaleSizeUnits = ' mm';
|
||||||
|
}
|
||||||
|
const textLines = [scaleSizeDisplayValue.toString().concat(scaleSizeUnits)];
|
||||||
|
return textLines;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ScaleOverlayTool.toolName = 'ScaleOverlay';
|
||||||
|
export default ScaleOverlayTool;
|
||||||
Loading…
Reference in New Issue