diff --git a/src/views/trials/trials-panel/reading/dicoms/components/Fusion/TableQuestionItem.vue b/src/views/trials/trials-panel/reading/dicoms/components/Fusion/TableQuestionItem.vue index abbf12c5..7bed9b4f 100644 --- a/src/views/trials/trials-panel/reading/dicoms/components/Fusion/TableQuestionItem.vue +++ b/src/views/trials/trials-panel/reading/dicoms/components/Fusion/TableQuestionItem.vue @@ -730,6 +730,30 @@ export default { }) return } + // 消失、无法评估状态的病灶限制不能测量SUV值 + var lesionState = this.getQuestionVal(7) + if ((lesionState === 2 || lesionState === 3) && this.questionForm.OtherMeasureData) { + this.$confirm(this.$t('评估状态为无法评估或消失的病灶不能测量SUV值!'), { + type: 'warning', + showCancelButton: false, + callback: action => {} + }) + return + } + // suv测量值可以测量为0,但不能与病灶、肝脏、纵隔血池绑定。 + if (this.questionForm.OtherMeasureData) { + console.log(this.questionForm.OtherMeasureData) + var suvmax = this.getQuestionVal(20) + if (suvmax === 0) { + this.$confirm(this.$t('当前病灶suv测量值为0,不允许保存!'), { + type: 'warning', + showCancelButton: false, + callback: action => {} + }) + return + } + } + const loading = this.$loading({ fullscreen: true }) var otherMeasureData = this.questionForm.OtherMeasureData ? Object.assign({}, this.questionForm.OtherMeasureData) : null if (otherMeasureData) { diff --git a/src/views/trials/trials-panel/reading/dicoms/components/Fusion/tools/CircleROITool.js b/src/views/trials/trials-panel/reading/dicoms/components/Fusion/tools/CircleROITool.js index 467bde77..69a70a6c 100644 --- a/src/views/trials/trials-panel/reading/dicoms/components/Fusion/tools/CircleROITool.js +++ b/src/views/trials/trials-panel/reading/dicoms/components/Fusion/tools/CircleROITool.js @@ -83,81 +83,81 @@ class CircleROITool extends cornerstoneTools.CircleROITool { // ) // this._getTextLines = this.getTextLines } - // addNewAnnotation = (evt) => { - // const eventDetail = evt.detail; - // const { currentPoints, element } = eventDetail; - // const worldPos = currentPoints.world; - // // const canvasPos = currentPoints.canvas; + addNewAnnotation = (evt) => { + const eventDetail = evt.detail; + const { currentPoints, element } = eventDetail; + const worldPos = currentPoints.world; + // const canvasPos = currentPoints.canvas; - // const enabledElement = getEnabledElement(element); - // const { viewport, renderingEngine } = enabledElement; + const enabledElement = getEnabledElement(element); + const { viewport, renderingEngine } = enabledElement; - // this.isDrawing = true; + this.isDrawing = true; - // const camera = viewport.getCamera(); - // const { viewPlaneNormal, viewUp } = camera; + const camera = viewport.getCamera(); + const { viewPlaneNormal, viewUp } = camera; - // const referencedImageId = this.getReferencedImageId( - // viewport, - // worldPos, - // viewPlaneNormal, - // viewUp - // ); + const referencedImageId = this.getReferencedImageId( + viewport, + worldPos, + viewPlaneNormal, + viewUp + ); - // const FrameOfReferenceUID = viewport.getFrameOfReferenceUID(); + const FrameOfReferenceUID = viewport.getFrameOfReferenceUID(); - // const annotation = { - // highlighted: true, - // invalidated: true, - // metadata: { - // toolName: this.getToolName(), - // viewPlaneNormal: [...viewPlaneNormal], - // viewUp: [...viewUp], - // FrameOfReferenceUID, - // referencedImageId, - // }, - // data: { - // label: '', - // handles: { - // textBox: { - // hasMoved: false, - // worldPosition: [0, 0, 0], - // worldBoundingBox: { - // topLeft: [0, 0, 0], - // topRight: [0, 0, 0], - // bottomLeft: [0, 0, 0], - // bottomRight: [0, 0, 0], - // }, - // }, - // points: [[...worldPos], [...worldPos]], - // activeHandleIndex: 1, - // }, - // cachedStats: {}, - // }, - // }; - // addAnnotation(annotation, element); + const annotation = { + highlighted: true, + invalidated: true, + metadata: { + toolName: this.getToolName(), + viewPlaneNormal: [...viewPlaneNormal], + viewUp: [...viewUp], + FrameOfReferenceUID, + referencedImageId, + }, + data: { + label: '', + handles: { + textBox: { + hasMoved: false, + worldPosition: [0, 0, 0], + worldBoundingBox: { + topLeft: [0, 0, 0], + topRight: [0, 0, 0], + bottomLeft: [0, 0, 0], + bottomRight: [0, 0, 0], + }, + }, + points: [[...worldPos], [...worldPos]], + activeHandleIndex: 1, + }, + cachedStats: {}, + }, + }; + addAnnotation(annotation, element); - // const viewportIdsToRender = getViewportIdsWithToolToRender( - // element, - // this.getToolName() - // ); + const viewportIdsToRender = getViewportIdsWithToolToRender( + element, + this.getToolName() + ); - // this.editData = { - // annotation, - // viewportIdsToRender, - // newAnnotation: true, - // hasMoved: false, - // }; - // this._activateDraw(element); + this.editData = { + annotation, + viewportIdsToRender, + newAnnotation: true, + hasMoved: false, + }; + this._activateDraw(element); - // hideElementCursor(element); + hideElementCursor(element); - // evt.preventDefault(); + evt.preventDefault(); - // triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender); + triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender); - // return annotation; - // }; + return annotation; + }; renderAnnotation = (enabledElement, svgDrawingHelper) => { let renderStatus = false const { viewport } = enabledElement @@ -421,7 +421,159 @@ class CircleROITool extends cornerstoneTools.CircleROITool { return renderStatus }; + _calculateCachedStats = ( + annotation, + viewport, + renderingEngine, + enabledElement, + modalityUnitOptions + ) => { + console.log('_calculateCachedStats') + const data = annotation.data + const { viewportId, renderingEngineId } = enabledElement + + const { points } = data.handles + + const canvasCoordinates = points.map((p) => viewport.worldToCanvas(p)) + const { viewPlaneNormal, viewUp } = viewport.getCamera() + + const [topLeftCanvas, bottomRightCanvas] = ( + getCanvasCircleCorners(canvasCoordinates) + ) + + const topLeftWorld = viewport.canvasToWorld(topLeftCanvas) + const bottomRightWorld = viewport.canvasToWorld(bottomRightCanvas) + const { cachedStats } = data + + const targetIds = Object.keys(cachedStats) + const worldPos1 = topLeftWorld + const worldPos2 = bottomRightWorld + for (let i = 0; i < targetIds.length; i++) { + const targetId = targetIds[i] + + const image = this.getTargetIdImage(targetId, renderingEngine) + + // If image does not exists for the targetId, skip. This can be due + // to various reasons such as if the target was a volumeViewport, and + // the volumeViewport has been decached in the meantime. + if (!image) { + continue + } + + const { dimensions, imageData, metadata } = image + + const worldPos1Index = transformWorldToIndex(imageData, worldPos1) + + worldPos1Index[0] = Math.floor(worldPos1Index[0]) + worldPos1Index[1] = Math.floor(worldPos1Index[1]) + worldPos1Index[2] = Math.floor(worldPos1Index[2]) + + const worldPos2Index = transformWorldToIndex(imageData, worldPos2) + + worldPos2Index[0] = Math.floor(worldPos2Index[0]) + worldPos2Index[1] = Math.floor(worldPos2Index[1]) + worldPos2Index[2] = Math.floor(worldPos2Index[2]) + + // Check if one of the indexes are inside the volume, this then gives us + // Some area to do stats over. + + if (this._isInsideVolume(worldPos1Index, worldPos2Index, dimensions)) { + const iMin = Math.min(worldPos1Index[0], worldPos2Index[0]) + const iMax = Math.max(worldPos1Index[0], worldPos2Index[0]) + + const jMin = Math.min(worldPos1Index[1], worldPos2Index[1]) + const jMax = Math.max(worldPos1Index[1], worldPos2Index[1]) + + const kMin = Math.min(worldPos1Index[2], worldPos2Index[2]) + const kMax = Math.max(worldPos1Index[2], worldPos2Index[2]) + + const boundsIJK = [ + [iMin, iMax], + [jMin, jMax], + [kMin, kMax] + ] + + const center = [ + (topLeftWorld[0] + bottomRightWorld[0]) / 2, + (topLeftWorld[1] + bottomRightWorld[1]) / 2, + (topLeftWorld[2] + bottomRightWorld[2]) / 2 + ] + + const ellipseObj = { + center, + xRadius: Math.abs(topLeftWorld[0] - bottomRightWorld[0]) / 2, + yRadius: Math.abs(topLeftWorld[1] - bottomRightWorld[1]) / 2, + zRadius: Math.abs(topLeftWorld[2] - bottomRightWorld[2]) / 2 + } + const { worldWidth, worldHeight } = getWorldWidthAndHeightFromTwoPoints( + viewPlaneNormal, + viewUp, + worldPos1, + worldPos2 + ) + const isEmptyArea = worldWidth === 0 && worldHeight === 0 + const scale = getCalibratedScale(image) + const aspect = getCalibratedAspect(image) + const area = Math.abs( + Math.PI * + (worldWidth / scale / 2) * + (worldHeight / aspect / scale / 2) + ) + + const modalityUnit = getModalityUnit( + metadata.Modality, + annotation.metadata.referencedImageId, + modalityUnitOptions + ) + const pointsInShape = pointInShapeCallback( + imageData, + (pointLPS, pointIJK) => pointInEllipse(ellipseObj, pointLPS), + this.configuration.statsCalculator.statsCallback, + boundsIJK + ) + + const stats = this.configuration.statsCalculator.getStatistics() + + cachedStats[targetId] = { + Modality: metadata.Modality, + area, + mean: stats[1] && stats[1].value ? stats[1].value : null, + max: stats[0] && stats[0].value ? stats[0].value : null, + stdDev: stats[2] && stats[2].value ? stats[2].value : null, + statsArray: stats, + pointsInShape: pointsInShape, + isEmptyArea, + areaUnit: getCalibratedAreaUnits(null, image), + radius: worldWidth / 2 / scale, + radiusUnit: getCalibratedLengthUnits(null, image), + perimeter: (2 * Math.PI * (worldWidth / 2)) / scale, + modalityUnit + } + } else { + this.isHandleOutsideImage = false + + cachedStats[targetId] = { + Modality: metadata.Modality + } + } + } + + annotation.invalidated = false + + // Dispatching annotation modified + const eventType = Enums.Events.ANNOTATION_MODIFIED + + const eventDetail = { + annotation, + viewportId, + renderingEngineId + } + triggerEvent(eventTarget, eventType, eventDetail) + + return cachedStats + } } + function getCanvasCircleCorners( circleCanvasPoints ) { diff --git a/src/views/trials/trials-panel/reading/dicoms/components/Lugano/QuestionList.vue b/src/views/trials/trials-panel/reading/dicoms/components/Lugano/QuestionList.vue index f92dff6c..bc18ae0e 100644 --- a/src/views/trials/trials-panel/reading/dicoms/components/Lugano/QuestionList.vue +++ b/src/views/trials/trials-panel/reading/dicoms/components/Lugano/QuestionList.vue @@ -680,6 +680,7 @@ export default { // 融合 handleMerge(answers, questionId, orderMark) { this.lesionData = [] + this.mergeList = [] this.merge.visible = true this.mergeInfo.questionId = questionId this.mergeInfo.mergeRowId = answers.RowId diff --git a/vue.config.js b/vue.config.js index 522793bd..2c8ec49a 100644 --- a/vue.config.js +++ b/vue.config.js @@ -63,7 +63,7 @@ module.exports = { // target: 'http://123.56.181.144:8000/api', // 国内测试环境 // target: 'http://123.56.94.154:8079', // 国内测试环境2 // target: 'http://123.56.94.154:7000', // 国内测试环境2 - target: 'http://123.56.94.154:30668', + target: 'http://123.56.94.154:30000', // target: 'http://123.56.181.144:7000', changeOrigin: true, secure: false,