343 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Plaintext
		
	
	
			
		
		
	
	
			343 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Plaintext
		
	
	
<template>
 | 
						|
  <div class="viewport_container" :class="['item',activeIndex === 1?'item_active':'']">
 | 
						|
    <div :id="`viewport${index}`" style="height: 100%;" />
 | 
						|
    <!-- 序列信息 -->
 | 
						|
    <div
 | 
						|
      v-if="seriesInfo.taskBlindName"
 | 
						|
      class="seriesInfo_wrapper"
 | 
						|
      :style="{color:index%2 == 1 ? '#ddd' : '#666'}"
 | 
						|
    >
 | 
						|
      <h2 v-if="isReadingShowSubjectInfo" class="taskInfo_container">
 | 
						|
        {{ subjectCode }} {{ seriesInfo.taskBlindName }}
 | 
						|
      </h2>
 | 
						|
      <div v-if="index === 1 || index === 2">
 | 
						|
        Series: #{{ seriesInfo.seriesNumber }}
 | 
						|
      </div>
 | 
						|
      <div v-if="index !== 4">Image: #{{ `${seriesInfo.imageIdIndex + 1} / ${seriesInfo.imageIds.length}` }}</div>
 | 
						|
      <div v-if="index === 1 || index === 2">{{ seriesInfo.modality }}</div>
 | 
						|
    </div>
 | 
						|
    <!-- 描述信息 -->
 | 
						|
    <div
 | 
						|
      v-if="seriesInfo.description && (index === 1 || index === 2)"
 | 
						|
      class="descInfo_wrapper"
 | 
						|
      :style="{color:index%2 == 1 ? '#ddd' : '#666'}"
 | 
						|
    >
 | 
						|
      <div>{{ seriesInfo.description }}</div>
 | 
						|
    </div>
 | 
						|
 | 
						|
    <!-- 图像信息 -->
 | 
						|
    <div
 | 
						|
      v-if="seriesInfo.description && (index === 1 || index === 2 || index === 3)"
 | 
						|
      class="imageInfo_wrapper_l"
 | 
						|
      :style="{color:index%2 == 1 ? '#ddd' : '#666'}"
 | 
						|
    >
 | 
						|
      <div v-show="mousePosition.index.length > 0">
 | 
						|
        Pos: {{ mousePosition.index[0] }}, {{ mousePosition.index[1] }}, {{ mousePosition.index[2] }}
 | 
						|
      </div>
 | 
						|
      <div v-if="(seriesInfo.modality === 'CT' || seriesInfo.modality === 'DR' || seriesInfo.modality === 'CR') && mousePosition.value">
 | 
						|
        HU: {{ mousePosition.value }}
 | 
						|
      </div>
 | 
						|
      <div v-else-if="(seriesInfo.modality === 'PT' && mousePosition.value)">
 | 
						|
        SUVbw(g/ml): {{ digitPlaces === -1 ?mousePosition.value.toFixed(3) :mousePosition.value.toFixed(digitPlaces) }}
 | 
						|
      </div>
 | 
						|
      <div v-else-if="mousePosition.value">
 | 
						|
        Density: {{ mousePosition.value }}
 | 
						|
      </div>
 | 
						|
      <div v-if="index === 1 || index === 2">
 | 
						|
        W*H: {{ imageInfo.size }}
 | 
						|
      </div>
 | 
						|
 | 
						|
      <div v-if="index === 1 || index === 2">Zoom: {{ imageInfo.zoom }}</div>
 | 
						|
    </div>
 | 
						|
    <div
 | 
						|
      v-if="seriesInfo.description && (index === 1 || index === 2 || index === 3)"
 | 
						|
      class="imageInfo_wrapper_r"
 | 
						|
      :style="{color:index%2 == 1 ? '#ddd' : '#666'}"
 | 
						|
    >
 | 
						|
      <div v-show="imageInfo.location && index !== 3 ">Location: {{ imageInfo.location }}</div>
 | 
						|
      <div v-show="seriesInfo.sliceThickness && index !== 3">Slice Thickness: {{ Number(seriesInfo.sliceThickness).toFixed(2) }}mm</div>
 | 
						|
      <div v-show="imageInfo.wwwc ">WW/WL: {{ imageInfo.wwwc }}</div>
 | 
						|
    </div>
 | 
						|
  </div>
 | 
						|
</template>
 | 
						|
<script>
 | 
						|
import {
 | 
						|
  getRenderingEngine,
 | 
						|
  metaData,
 | 
						|
  utilities,
 | 
						|
  // cache,
 | 
						|
  // StackViewport,
 | 
						|
  // BaseVolumeViewport,
 | 
						|
  // getEnabledElement,
 | 
						|
  // getEnabledElementByIds,
 | 
						|
  // eventTarget,
 | 
						|
  Enums } from '@cornerstonejs/core'
 | 
						|
// import * as cornerstonejs from '@cornerstonejs/core'
 | 
						|
// import * as cornerstoneTools from '@cornerstonejs/tools'
 | 
						|
import {
 | 
						|
  utilities as toosUtilities
 | 
						|
} from '@cornerstonejs/tools'
 | 
						|
const {
 | 
						|
  VOLUME_NEW_IMAGE
 | 
						|
  // VOLUME_LOADED,
 | 
						|
  // IMAGE_VOLUME_MODIFIED,
 | 
						|
  // VOLUME_VIEWPORT_NEW_VOLUME
 | 
						|
} = Enums.Events
 | 
						|
 | 
						|
var renderingEngine
 | 
						|
var viewport
 | 
						|
export default {
 | 
						|
  name: 'Viewport',
 | 
						|
  props: {
 | 
						|
    activeIndex: {
 | 
						|
      type: Number,
 | 
						|
      default: -1
 | 
						|
    },
 | 
						|
    index: {
 | 
						|
      // 1:ct  2:pet  3:fusion  4:mip
 | 
						|
      type: Number,
 | 
						|
      required: true
 | 
						|
    },
 | 
						|
    isReadingShowSubjectInfo: {
 | 
						|
      type: Boolean,
 | 
						|
      default: false
 | 
						|
    },
 | 
						|
    seriesInfo: {
 | 
						|
      type: Object,
 | 
						|
      default() {
 | 
						|
        return {}
 | 
						|
      }
 | 
						|
    },
 | 
						|
    renderingEngineId: {
 | 
						|
      type: String,
 | 
						|
      required: true
 | 
						|
    },
 | 
						|
    viewportId: {
 | 
						|
      type: String,
 | 
						|
      required: true
 | 
						|
    },
 | 
						|
    volume: {
 | 
						|
      type: Object,
 | 
						|
      default() {
 | 
						|
        return {}
 | 
						|
      }
 | 
						|
    },
 | 
						|
    isRender: {
 | 
						|
      type: Boolean,
 | 
						|
      default: false
 | 
						|
    }
 | 
						|
  },
 | 
						|
  data() {
 | 
						|
    return {
 | 
						|
      subjectCode: '',
 | 
						|
      mousePosition: { index: [], value: null, modalityUnit: '', world: [], ctVal: null, ptVal: null },
 | 
						|
      digitPlaces: -1,
 | 
						|
      imageInfo: {
 | 
						|
        zoom: null,
 | 
						|
        size: null,
 | 
						|
        location: null,
 | 
						|
        sliceThickness: null,
 | 
						|
        wwwc: null
 | 
						|
      }
 | 
						|
    }
 | 
						|
  },
 | 
						|
  watch: {
 | 
						|
    isRender: {
 | 
						|
      handler(v) {
 | 
						|
        this.$nextTick(() => {
 | 
						|
          // this.initViewport()
 | 
						|
        })
 | 
						|
      }
 | 
						|
    },
 | 
						|
    deep: true
 | 
						|
  },
 | 
						|
  mounted() {
 | 
						|
    console.log(toosUtilities)
 | 
						|
    this.subjectCode = this.$route.query.subjectCode
 | 
						|
    var element = document.getElementById(`viewport${this.index}`)
 | 
						|
 | 
						|
    element.addEventListener(VOLUME_NEW_IMAGE, this.handleVoluneNewImage)
 | 
						|
    element.addEventListener(Enums.Events.CAMERA_MODIFIED, this.handleCameraModified)
 | 
						|
    element.addEventListener(Enums.Events.VOI_MODIFIED, this.handleVOIModified)
 | 
						|
    element.addEventListener(Enums.Events.MOUSE_MOVE, this.handleVOIModified)
 | 
						|
    // element.addEventListener('mousemove', this.handleMouseMove)
 | 
						|
    if (this.index !== 4) {
 | 
						|
      element.addEventListener('CORNERSTONE_TOOLS_MOUSE_MOVE', this.handleMouseMove)
 | 
						|
    }
 | 
						|
    element.addEventListener('mouseleave', this.handleMouseLeave)
 | 
						|
  },
 | 
						|
  methods: {
 | 
						|
    handleVoluneNewImage(e) {
 | 
						|
      const { imageIndex } = e.detail
 | 
						|
      this.seriesInfo.imageIdIndex = imageIndex
 | 
						|
      renderingEngine = getRenderingEngine(this.renderingEngineId)
 | 
						|
      viewport = renderingEngine.getViewport(this.viewportId)
 | 
						|
      if (viewport) {
 | 
						|
        var zoom = viewport.getZoom()
 | 
						|
        if (zoom) {
 | 
						|
          this.imageInfo.zoom = zoom.toFixed(4)
 | 
						|
        }
 | 
						|
        var imageId = viewport.getCurrentImageId()
 | 
						|
        if (imageId) {
 | 
						|
          const imagePlaneModule = metaData.get('imagePlaneModule', imageId)
 | 
						|
          this.imageInfo.size = `${imagePlaneModule.columns}*${imagePlaneModule.rows}`
 | 
						|
          this.imageInfo.location = imagePlaneModule.sliceLocation
 | 
						|
          this.getOrientationMarker(imagePlaneModule)
 | 
						|
        }
 | 
						|
        var properties = viewport.getProperties()
 | 
						|
        if (properties && properties.voiRange) {
 | 
						|
          var { lower, upper } = properties.voiRange
 | 
						|
          const { windowWidth, windowCenter } = utilities.windowLevel.toWindowLevel(
 | 
						|
            lower,
 | 
						|
            upper
 | 
						|
          )
 | 
						|
          this.imageInfo.wwwc = `${Math.round(windowWidth)}/${Math.round(windowCenter)}`
 | 
						|
        }
 | 
						|
      }
 | 
						|
    },
 | 
						|
    getOrientationMarker(imagePlane) {
 | 
						|
      // const enabledElement = cornerstone.getEnabledElement(element)
 | 
						|
      // const imagePlane = cornerstone.metaData.get(
 | 
						|
      //   'imagePlaneModule',
 | 
						|
      //   enabledElement.image.imageId
 | 
						|
      // )
 | 
						|
 | 
						|
      if (!imagePlane || !imagePlane.rowCosines || !imagePlane.columnCosines) {
 | 
						|
        return
 | 
						|
      }
 | 
						|
      console.log(imagePlane.rowCosines)
 | 
						|
      const row = toosUtilities.orientation.getOrientationStringLPS(imagePlane.rowCosines)
 | 
						|
      const column = toosUtilities.orientation.getOrientationStringLPS(imagePlane.columnCosines)
 | 
						|
      const oppositeRow = toosUtilities.orientation.invertOrientationStringLPS(row)
 | 
						|
      const oppositeColumn = toosUtilities.orientation.invertOrientationStringLPS(column)
 | 
						|
      // const markers = {
 | 
						|
      //   top: oppositeColumn,
 | 
						|
      //   bottom: column,
 | 
						|
      //   left: oppositeRow,
 | 
						|
      //   right: row
 | 
						|
      // }
 | 
						|
      // if (!markers) {
 | 
						|
      //   return
 | 
						|
      // }
 | 
						|
      // this.orientationMarkers = [oppositeColumn, row, column, oppositeRow]
 | 
						|
      // this.originalMarkers = [oppositeColumn, row, column, oppositeRow]
 | 
						|
      console.log(oppositeColumn, row, column, oppositeRow)
 | 
						|
      // this.setMarkers()
 | 
						|
    },
 | 
						|
    handleCameraModified(e) {
 | 
						|
      renderingEngine = getRenderingEngine(this.renderingEngineId)
 | 
						|
      viewport = renderingEngine.getViewport(this.viewportId)
 | 
						|
      if (!viewport) return
 | 
						|
      var zoom = viewport.getZoom()
 | 
						|
      if (!zoom) return
 | 
						|
      this.imageInfo.zoom = zoom.toFixed(4)
 | 
						|
    },
 | 
						|
    handleVOIModified(e) {
 | 
						|
      renderingEngine = getRenderingEngine(this.renderingEngineId)
 | 
						|
      viewport = renderingEngine.getViewport(this.viewportId)
 | 
						|
      if (!viewport) return
 | 
						|
      var properties = viewport.getProperties()
 | 
						|
      if (properties && properties.voiRange) {
 | 
						|
        var { lower, upper } = properties.voiRange
 | 
						|
        const { windowWidth, windowCenter } = utilities.windowLevel.toWindowLevel(
 | 
						|
          lower,
 | 
						|
          upper
 | 
						|
        )
 | 
						|
        this.imageInfo.wwwc = `${Math.round(windowWidth)}/${Math.round(windowCenter)}`
 | 
						|
      }
 | 
						|
    },
 | 
						|
    handleMouseMove(e) {
 | 
						|
      // console.log(e)
 | 
						|
      // renderingEngine = getRenderingEngine(this.renderingEngineId)
 | 
						|
      // viewport = renderingEngine.getViewport(this.viewportId)
 | 
						|
      // const targetId = this.getTargetId(viewport)
 | 
						|
      // console.log(targetId)
 | 
						|
      // var imageId = viewport.getCurrentImageId()
 | 
						|
      const { currentPoints } = e.detail
 | 
						|
      const worldPoint = currentPoints.world
 | 
						|
      // const modalityUnitOptions = {
 | 
						|
      //   isPreScaled: cornerstoneTools.utilities.viewport.isViewportPreScaled(viewport, targetId),
 | 
						|
      //   isSuvScaled: this.isSuvScaled(viewport, targetId, imageId)
 | 
						|
      // }
 | 
						|
      // var obj = this.calculateSuv(worldPoint, imageId, modalityUnitOptions)
 | 
						|
      const { imageData } = this.volume
 | 
						|
      const index = imageData.worldToIndex(worldPoint)
 | 
						|
 | 
						|
      index[0] = Math.floor(index[0])
 | 
						|
      index[1] = Math.floor(index[1])
 | 
						|
      index[2] = Math.floor(index[2])
 | 
						|
      this.mousePosition.index = index
 | 
						|
 | 
						|
      this.mousePosition.value = this.getValue(this.volume, worldPoint)
 | 
						|
    },
 | 
						|
    getValue(volume, worldPos) {
 | 
						|
      const { dimensions, scalarData, imageData } = volume
 | 
						|
 | 
						|
      const index = imageData.worldToIndex(worldPos)
 | 
						|
 | 
						|
      index[0] = Math.floor(index[0])
 | 
						|
      index[1] = Math.floor(index[1])
 | 
						|
      index[2] = Math.floor(index[2])
 | 
						|
 | 
						|
      if (!utilities.indexWithinDimensions(index, dimensions)) {
 | 
						|
        return
 | 
						|
      }
 | 
						|
 | 
						|
      const yMultiple = dimensions[0]
 | 
						|
      const zMultiple = dimensions[0] * dimensions[1]
 | 
						|
 | 
						|
      const value =
 | 
						|
  scalarData[index[2] * zMultiple + index[1] * yMultiple + index[0]]
 | 
						|
 | 
						|
      return value
 | 
						|
    },
 | 
						|
    handleMouseLeave(e) {
 | 
						|
      this.mousePosition.index = []
 | 
						|
      this.mousePosition.value = null
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
</script>
 | 
						|
<style lang="scss" scoped>
 | 
						|
.viewport_container{
 | 
						|
  height: 100%;
 | 
						|
  .seriesInfo_wrapper {
 | 
						|
    position: absolute;
 | 
						|
    left: 10px;
 | 
						|
    top: 10px;
 | 
						|
    text-align: left;
 | 
						|
    font-size: 12px;
 | 
						|
    z-index: 1;
 | 
						|
    .taskInfo_container{
 | 
						|
      color:#f44336;
 | 
						|
      padding: 5px 0px;
 | 
						|
      margin: 0;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  .descInfo_wrapper{
 | 
						|
    position: absolute;
 | 
						|
    right: 10px;
 | 
						|
    top: 10px;
 | 
						|
    text-align: right;
 | 
						|
    font-size: 12px;
 | 
						|
    z-index: 1;
 | 
						|
  }
 | 
						|
  .imageInfo_wrapper_l{
 | 
						|
    position: absolute;
 | 
						|
    left: 10px;
 | 
						|
    bottom: 10px;
 | 
						|
    text-align: left;
 | 
						|
    font-size: 12px;
 | 
						|
    z-index: 1;
 | 
						|
  }
 | 
						|
  .imageInfo_wrapper_r{
 | 
						|
    position: absolute;
 | 
						|
    right: 10px;
 | 
						|
    bottom: 10px;
 | 
						|
    text-align: right;
 | 
						|
    font-size: 12px;
 | 
						|
    z-index: 1;
 | 
						|
  }
 | 
						|
}
 | 
						|
</style>
 |