tangjunhao 1 місяць тому
батько
коміт
5e74b76e6e
2 змінених файлів з 545 додано та 1 видалено
  1. 532 0
      src/view/index/explode3d.vue
  2. 13 1
      src/view/index/first-left.vue

+ 532 - 0
src/view/index/explode3d.vue

@@ -0,0 +1,532 @@
+<template>
+  <div v-show="isexpdialog" class="dialog_class4 bgcolor tianjia  foter_l tianjia">
+    <div class="expcontent">
+      <h1 class="headertiele">{{ titleName }}</h1>
+    <div class="exp">
+      <div class="expleft" id="expleft1"></div>
+      <div class="expright">
+        <!-- 物理量 -->
+        <div class="heigjie  imgneon">
+          <div class="he_pading1 color1">
+            <el-form-item label="物理量:">
+              <el-config-provider :locale="zhCn">
+                <el-select v-model="formInline.region" @change="regionchange($event)" placeholder="请选择">
+                  <el-option v-for="item in strResultFormatlist" :key="item.id" :label="item.name"
+                    :value="item.value"></el-option>
+                </el-select>
+              </el-config-provider>
+            </el-form-item>
+
+          </div>
+        </div>
+        <!-- 动画 -->
+        <el-aside class="L_aside L_aside1 asideg asidegbg leftbgimg1">
+          <div class="demo-collapse jiance asideg1 jc_header collapseeion jianstyle">
+            <el-collapse accordion v-model="activeNames1" class="bganimation">
+              <el-collapse-item name="2" class="imgneon">
+                <template #title>
+                  <el-icon class="iconimg Frame3" fit="contain"></el-icon>
+                  动画展示
+                </template>
+                <div class="rg_content">
+                  <div class="rg-padding">
+                    <div class="animation_s">
+                      <el-slider :max="endtime" :min="1" v-model="count" @change="sliderchange">
+                      </el-slider>
+                      <div class="tanniu">
+                        <div><el-image :src="t1" fit="contain" @click="Prev"></el-image></div>
+                        <div v-show="suspendshow"><el-image :src="t2" fit="contain" @click="play(500)"></el-image></div>
+                        <div v-show="playshow"><el-image :src="t3" fit="contain" @click="play(500)"></el-image></div>
+                        <div><el-image :src="t4" fit="contain" @click="increment"></el-image></div>
+
+                      </div>
+                    </div>
+
+
+                  </div>
+                </div>
+                <!-- <div class="mgsnoe" style="height: 200px"></div> -->
+              </el-collapse-item>
+            </el-collapse>
+          </div>
+        </el-aside>
+      </div>
+    </div>
+      <div class="dialog-footer footer_div l_btn">
+            <div class="footerbtn flex1">
+                <div class="borderimg"><el-button @click="isexpdialog = false">取消</el-button></div>
+            </div>
+            <div class="footerbtn flex1">
+                <div class="borderimg"><el-button  @click="quding()">
+                        确定
+                    </el-button></div>
+            </div>
+        </div>
+    </div>
+ 
+  </div>
+  <!-- 瓦斯爆炸弹出列表-->
+</template>
+<script setup>
+import zhCn from "element-plus/es/locale/lang/zh-cn"
+import { ref, onMounted, reactive } from "vue"
+import { RouterView, RouterLink } from "vue-router"
+import { request, uploadFile } from "@/utils/request"
+import { ElMessage, ElButton, ElDialog, ElSelect } from "element-plus"
+import { createGassControl } from "@/control/gassControl.js"
+import emitter from "@/utils/emitter"
+
+import t1 from "@/assets/img/t1.png"
+import t2 from "@/assets/img/t2.png"
+import t3 from "@/assets/img/t3.png"
+import t4 from "@/assets/img/t4.png"
+
+import * as d3 from "d3-scale";
+import { formatDefaultLocale } from "d3-format";
+import vtkGenericRenderWindow from '@kitware/vtk.js/Rendering/Misc/GenericRenderWindow';
+import vtkRenderWindowWithControlBar from "@kitware/vtk.js/Rendering/Misc/RenderWindowWithControlBar";
+import vtkActor from "@kitware/vtk.js/Rendering/Core/Actor";
+import vtkConeSource from "@kitware/vtk.js/Filters/Sources/ConeSource";
+import vtkMapper from "@kitware/vtk.js/Rendering/Core/Mapper";
+import { Representation } from "@kitware/vtk.js/Rendering/Core/Property/Constants";
+import vtkScalarBarActor from "@kitware/vtk.js/Rendering/Core/ScalarBarActor";
+import vtkColorTransferFunction from "@kitware/vtk.js/Rendering/Core/ColorTransferFunction";
+import vtkDataArray from "@kitware/vtk.js/Common/Core/DataArray.js";
+import vtkLight from "@kitware/vtk.js/Rendering/Core/Light";
+
+const props = defineProps({
+  aid: Number
+})
+let isexpdialog = ref(false)
+const strResultFormatlist = ref([])
+const formInline = ref({
+  user: "11",
+  region: "u-velocity",
+  name: "x方向速度(m/s)",
+  date: ""
+})
+
+const titleName = ref("瓦斯爆炸演化")
+
+const nameMap = {
+  "u-velocity": 'x方向速度(m/s)',
+  "v-velocity": 'y方向速度(m/s)',
+  "w-velocity": 'z方向速度(m/s)',
+  "static_pressure": '压力(Pa)',
+  "static_temperature": '温度(℃)',
+  "O2_mass_fraction": '氧气质量分数(%)',
+  "CH4_mass_fraction": '甲烷质量分数(%)',
+  "CO2_mass_fraction": '二氧化碳质量分数(%)',
+  "H2O_mass_fraction": '水蒸气质量分数(%)',
+  "N2_mass_fraction": '氮气质量分数(%)'
+};
+
+
+let arr=[];
+let currentrow1 = ref(false)
+let activeNames1 = ref(["2"])
+let starttime = ref(1)
+let endtime = ref(60)   
+let count = ref(1)
+let newcount = ref(0)
+let timenum = ref(2)
+let playshow = ref(true)
+const isstop = ref(false)
+let suspendshow = ref(false)
+let showfalse = ref(false)
+let initFlag=false;
+let aid = ref()
+let vtkObj = {}
+let max, min;
+watch(
+  () => [formInline.value.region, count.value, aid.value],
+  (newVal, oldVal) => {
+  
+    if(initFlag){
+      console.log(count.value);
+       if (newVal[1] != oldVal[1]) {
+      console.log("步数改变", newVal[1], oldVal[1]);
+      if (vtkObj.fcon) {
+        console.log(count.value);
+        vtkScalarRead(count.value); //步数
+      }
+    }
+    if (newVal[0] != oldVal[0]) {
+      console.log("标量改变", newVal[0], oldVal[0]);
+      if (vtkObj.fcon) {
+        vtkShow();
+      }
+    }
+
+    }
+  },
+  { deep: true }
+); //深度监视
+onMounted(() => {
+  const rootContainer = document.getElementById("expleft1")
+  // rootContainer.style.position = "relative"
+  // rootContainer.style.width = "100%"
+  // rootContainer.style.height = "100%"
+  vtkObj.fcon = createGassControl();
+  const fcon = vtkObj.fcon;
+  vtkObj.renderWindow = vtkGenericRenderWindow.newInstance()
+  vtkObj.renderWindow.setContainer(rootContainer)
+  vtkObj.jgMapper = vtkMapper.newInstance()
+  vtkObj.jgActor = vtkActor.newInstance()
+  vtkObj.jgActor.getProperty().setRepresentation(Representation.SURFACE) //面
+  vtkObj.jgActor.setMapper(vtkObj.jgMapper)
+  // vtkObj.renderWindow.getRenderer().addActor(vtkObj.jgActor);
+  vtkObj.renderWindow.getRenderer().setBackground(0.0, 0.0, 0.0, 0.0)
+
+  vtkObj.scalarBarActor = vtkScalarBarActor.newInstance()
+  vtkObj.scalarBarActor.setGenerateTicks(generateTicks(5))
+  vtkObj.scalarBarActor.setDrawAboveRangeSwatch(true)
+  vtkObj.scalarBarActor.setDrawNanAnnotation(false)
+  vtkObj.scalarBarActor.setBoxPosition([1, 0])
+  // 修改设条颜色
+  const ctf = vtkColorTransferFunction.newInstance()
+  ctf.addRGBPoint(0.0, 0, 1, 154 / 255.0)
+  ctf.addRGBPoint(1.0, 1.0, 165.0 / 255.0, 0.0)
+  ctf.addRGBPoint(2.0, 230 / 255.0, 0.0, 92.0 / 225.0)
+  vtkObj.jgMapper.setLookupTable(ctf)
+  const lut = vtkObj.jgMapper.getLookupTable()
+  vtkObj.scalarBarActor.setScalarsToColors(lut)
+  vtkObj.renderWindow.resize()
+  // vtkObj.renderWindow.getRenderer().addActor(vtkObj.scalarBarActor);
+  // vtkGridRead(props.aid);
+  // vtkObj.renderWindow.getRenderer().resetCamera();
+  // vtkObj.renderWindow.getRenderWindow().render();
+  // 设置环境光和光照
+  const light = vtkLight.newInstance()
+  light.setColor(1.0, 1.0, 1.0) // 白色环境光
+  light.setIntensity(3.0) // 强度为1.0
+  vtkObj.renderWindow.getRenderer().addLight(light)
+
+  emitter.on("pipeName", handleTitleName)
+})
+
+onUnmounted(() => {
+  emitter.off("pipeName", handleTitleName)
+})
+
+function handleTitleName(name) {
+  console.log("接收到的管道名称:", name);
+  titleName.value = `${name}(灾源点巷道)局部图`;
+}
+
+function initVtk() {
+
+}
+function generateTicks(numberOfTicks) {
+  return (helper) => {
+    const lastTickBounds = helper.getLastTickBounds()
+    // compute tick marks for axes
+    const scale = d3
+      .scaleLinear()
+      .domain([0.0, 1.0])
+      .range([lastTickBounds[0], lastTickBounds[1]])
+    const samples = scale.ticks(numberOfTicks)
+    const ticks = samples.map((tick) => scale(tick))
+    // Replace minus "\u2212" with hyphen-minus "\u002D" so that parseFloat() works
+    formatDefaultLocale({ minus: "\u002D" })
+    const format = scale.tickFormat(
+      ticks[0],
+      ticks[ticks.length - 1],
+      numberOfTicks
+    )
+    const tickStrings = ticks
+      .map(format)
+      .map((tick) => Number(parseFloat(tick).toPrecision(12)).toPrecision()) // d3 sometimes adds unwanted whitespace
+    helper.setTicks(ticks)
+    helper.setTickStrings(tickStrings)
+  }
+}
+
+
+let cameraInitialized = false; // 默认还未初始化相机
+
+function vtkShow() {
+  console.log("执行了 vtkShow");
+  const scalarBarActor = vtkObj.scalarBarActor
+  const mapper = vtkObj.jgMapper
+  const actor = vtkObj.jgActor
+  const fcon = vtkObj.fcon
+
+  const scalarArray = fcon.scalar.get(formInline.value.region)
+  if (!scalarArray || !fcon.polydata) {
+    return
+  }
+
+  const dataArray = vtkDataArray.newInstance({
+    name: formInline.value.region,
+    size: fcon.polydata.getNumberOfPoints()
+  })
+
+  dataArray.setData(scalarArray)
+  fcon.polydata.getPointData().setScalars(dataArray)
+  mapper.setInputData(fcon.polydata)
+
+  getMinMax(scalarArray)
+  mapper.setScalarRange(parseFloat(min.toFixed(3)), parseFloat(max.toFixed(3)))
+  scalarBarActor.setAxisLabel(formInline.value.name)
+
+  mapper.clearColorArrays()
+  actor.getProperty().setOpacity(count.value)
+
+  vtkObj.renderWindow.getRenderer().addActor(scalarBarActor)
+  vtkObj.renderWindow.getRenderer().addActor(actor)
+
+  // 仅第一次调用 resetCamera
+  if (!cameraInitialized) {
+    vtkObj.renderWindow.getRenderer().resetCamera()
+    cameraInitialized = true
+  }
+
+  vtkObj.renderWindow.getRenderWindow().render()
+  vtkObj.renderWindow.resize()
+  initFlag = true
+}
+
+
+
+function getMinMax(scalars) {
+  // console.log("getMinMax:",scalars);
+  min = scalars[0]
+  max = scalars[0]
+  for (let index = 0; index <= scalars.length; index++) {
+    let scalar = scalars[index]
+    if (min > scalar) {
+      min = scalar
+    }
+    if (max < scalar) {
+      max = scalar
+    }
+  }
+  console.log("max,min:", max, min);
+}
+onBeforeUnmount(() => {
+  vtkObj.scalarBarActor.delete()
+  vtkObj.jgMapper.delete()
+  vtkObj.jgActor.delete()
+  vtkObj.renderWindow.delete()
+  vtkObj = null
+})
+// 播放暂停
+const play = (time) => {
+  const fcon = vtkObj.fcon;
+  showfalse.value = !showfalse.value
+  currentrow1.value = false
+  if (showfalse.value) {
+    suspendshow.value = true
+    playshow.value = false
+    isstop.value = true //播放
+    const sleep = (timeout = time) =>
+      new Promise((resolve, reject) => {
+        setTimeout(resolve, timeout)
+      })
+    let timer = async (timeout) => {
+      while (count.value < endtime.value && isstop.value) {
+        if (isstop.value == true) {
+          await sleep(time)
+          count.value++
+          fcon.step = count.value
+          newcount.value = count.value
+          // newtime();
+        }
+        
+        
+      }
+      isstop.value = false //暂停
+          playshow.value = true
+          suspendshow.value = false
+    }
+
+    timer(time)
+  } else {
+    isstop.value = false //暂停
+    playshow.value = true
+    suspendshow.value = false
+  }
+}
+//  下一页
+function increment() {
+  const fcon = vtkObj.fcon
+  currentrow1.value = false
+  isstop.value = false
+  if (count.value == endtime.value) {
+    return
+  }
+  count.value++
+  newcount.value = count.value
+  fcon.step = count.value
+  //newtime();
+}
+//回到上一页
+function Prev() {
+  const fcon = vtkObj.fcon
+  currentrow1.value = false
+  isstop.value = false
+  count.value--
+  fcon.step = count.value
+  newcount.value = count.value
+  //newtime();
+}
+// 时间计算
+const newtime = () => {
+  timeshow.value = true
+  time.value = null
+  oldtime.value = sessionStorage.getItem("acctime")
+  console.log(oldtime.value)
+  time.value = new Date(oldtime.value).getTime() / 1000
+  if (count.value == 2) {
+    let time2 = (count.value - 1) * 60 + time.value
+    timeline.value = timescount(time2)
+  } else {
+    let time2 = count.value * 60 + time.value
+    timeline.value = timescount(time2)
+  }
+}
+function sliderchange(val) {
+
+  const fcon = vtkObj.fcon
+
+  suspendshow.value = false
+  playshow.value = true
+  isstop.value = false
+  newcount.value = count.value
+  fcon.step = count.value
+}
+function vtkGridRead() {
+  initVtk();
+  const fcon = vtkObj.fcon
+  aid.value = props.aid
+  fcon.step = count.value
+  fcon.aid = aid.value
+  const params = {
+    transCode: "D40003",
+    aid: aid.value
+  }
+  request(params).then((res) => {
+    endtime.value = res.steps
+    fcon
+      .initGemetry(aid.value)
+      .then((result) => {
+        vtkScalarRead(count.value) //步数
+      })
+      .catch((err) => { })
+  
+  }).catch((err) => { })
+}
+function vtkScalarRead(step) {
+  arr=[];
+  let i=0;
+  const fcon = vtkObj.fcon
+  console.log('fcon:',fcon);
+  fcon
+    .getScalrsByStep(step)
+    .then((result) => {
+     // console.log(fcon.scalar)
+     strResultFormatlist.value = [];
+      fcon.scalar.forEach((value, key) => {
+        //arr.push(key)
+        if (nameMap[key]) {
+          i=i+1
+          strResultFormatlist.value.push({
+              id: i,
+              name:nameMap[key] || key ,
+              value:key ,
+          });
+        }
+      })
+    console.log('strResultFormatlist:',strResultFormatlist.value);
+      vtkShow()
+    })
+    .catch((err) => {
+      console.log(err)
+    })
+}
+ //深度监视
+const regionchange=(val)=>{
+  formInline.value.region=val;
+  formInline.value.name=nameMap[val] || val;
+}
+const quding=()=>{
+  isexpdialog.value=false;
+}
+defineExpose({ isexpdialog, vtkGridRead })
+</script>
+<style  lang="scss" scoped>
+.exp {
+  display: flex;
+
+  .expleft {
+    width: 70%;
+    border-radius: 0px 0px 0px 0px;
+    border: 1px solid;
+    border-image: linear-gradient(180deg,
+        rgba(31, 107, 255, 1),
+        rgba(31, 107, 255, 0.48)) 1 1;
+    box-shadow: inset 0px 0px 17px 5px rgba(12, 97, 197, 0.2);
+    margin-right: 2%;
+    height: 600px;
+  }
+
+  .expright {
+    padding: 10px;
+    width: 340px;
+    border-radius: 0px 0px 0px 0px;
+    border: 1px solid;
+    border-image: linear-gradient(180deg,
+        rgba(31, 107, 255, 1),
+        rgba(31, 107, 255, 0.48)) 1 1;
+    box-shadow: inset 0px 0px 17px 5px rgba(12, 97, 197, 0.2);
+  }
+}
+
+.tanniu {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.expcontent {
+  position: absolute;
+  left: 25%;
+  top: 100px;
+  width: 50%;
+
+  padding: 10px;
+  z-index: 11111;
+  background-color:rgba(13, 22, 57, 0.96);
+  border: 1px solid;
+  border-image: linear-gradient(180deg,
+      rgba(31, 107, 255, 1),
+      rgba(31, 107, 255, 0.48)) 1 1;
+  box-shadow: inset 0px 0px 17px 5px rgba(12, 97, 197, 0.2);
+}
+.headertiele{
+  color: #fff;
+  text-align: left;
+  padding: 0 20px;
+  font-size: 16px;
+  font-family: 'YouShe';
+}
+// #expleft1{
+//   width:750px;
+//   height:500px;
+//   left:25%;
+//   top: 25%;
+//   background-color:rgba(12, 97, 197, 1);
+//   border: 1px solid;
+//     border-image: linear-gradient(
+//         180deg,
+//         rgba(31, 107, 255, 1),
+//         rgba(31, 107, 255, 0.48)
+//       )
+//       1 1;
+//     box-shadow: inset 0px 0px 17px 5px rgba(12, 97, 197, 0.2);
+//   position: absolute;
+//   z-index: 11111;
+//   color: #fff;
+// }
+</style>

+ 13 - 1
src/view/index/first-left.vue

@@ -19,9 +19,12 @@
                     <el-switch v-model="valueswitch" inline-prompt @change="swutchfun($event)"
                       style="--el-switch-on-color:#ff4949; --el-switch-off-color: #525050" active-text="是"
                       inactive-text="否" />
-                    <div class="re_tele2" v-if="props.classradio == 'Gass1' || props.classradio =='Gass'">
+                    <div class="re_tele2" v-if="props.classradio == 'Gass1'">
                       <div class="btn" @click="explode()">爆炸演化</div>
                     </div>
+                    <div class="re_tele2" v-if="props.classradio =='Gass'">
+                      <div class="btn" @click="explode3d()">爆炸演化</div>
+                    </div>
                   </div>
                   <div class="he_pading color1  wusele">
                     <el-form-item label="物理量:"
@@ -196,6 +199,7 @@
   </div>
   <htmldialog ref="htmldialogref" :classradio="props.classradio" :isshow='isshow' @funidshow="funidshow" />
   <exploderow ref="exploderef" :aid="aid" />
+  <exploderow3d ref="explode3dref" :aid="aid" />
 </template>
 <script setup>
 import { ref, onMounted, reactive, } from "vue";
@@ -221,7 +225,9 @@ import htmldialog from "./htmldialog.vue"
 import VFitColumns from 'v-fit-columns';
 import emitter from "@/utils/emitter";
 import exploderow from "./explode.vue"
+import exploderow3d from "./explode3d.vue"
 let exploderef = ref();
+let explode3dref = ref();
 let firstshow = ref(false);
 let timeshow = ref(true);
 let valueswitch = ref(false);
@@ -1138,6 +1144,12 @@ const explode = () => {
   exploderef.value.isexpdialog = true;
   exploderef.value.vtkGridRead();
 }
+
+const explode3d = () => {
+  explode3dref.value.isexpdialog = true;
+  explode3dref.value.vtkGridRead();
+}
+
 onUnmounted(() => {
   emitter.off('handleSelect')
 })