|  | @@ -1,193 +0,0 @@
 | 
	
		
			
				|  |  | -<template>
 | 
	
		
			
				|  |  | -  <div ref="threeContainer" class="three-container"></div>
 | 
	
		
			
				|  |  | -</template>
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -<script setup>
 | 
	
		
			
				|  |  | -import { ref, onMounted, onUnmounted, watch } from "vue";
 | 
	
		
			
				|  |  | -import * as THREE from "three";
 | 
	
		
			
				|  |  | -import { VTKParserFactory } from "../utils/parsers/VTKParserFactory";
 | 
	
		
			
				|  |  | -import { UnstructuredGridRenderer } from "../utils/renderers/UnstructuredGridRenderer";
 | 
	
		
			
				|  |  | -import { PolyDataRenderer } from "../utils/renderers/PolyDataRenderer";
 | 
	
		
			
				|  |  | -import {
 | 
	
		
			
				|  |  | -  initScene,
 | 
	
		
			
				|  |  | -  initCamera,
 | 
	
		
			
				|  |  | -  initRenderer,
 | 
	
		
			
				|  |  | -  animateScene,
 | 
	
		
			
				|  |  | -  cleanupScene,
 | 
	
		
			
				|  |  | -  initControls,
 | 
	
		
			
				|  |  | -  initAxesHelper
 | 
	
		
			
				|  |  | -} from "../utils/threeUtils";
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -const props = defineProps({
 | 
	
		
			
				|  |  | -  vtkData: {
 | 
	
		
			
				|  |  | -    type: Object,
 | 
	
		
			
				|  |  | -    required: true,
 | 
	
		
			
				|  |  | -  },
 | 
	
		
			
				|  |  | -});
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -const threeContainer = ref(null);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -let scene, camera, renderer, controls, axesHelper;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// 创建坐标系指示器
 | 
	
		
			
				|  |  | -const createAxesHelper = () => {
 | 
	
		
			
				|  |  | -  const axesHelper = new THREE.AxesHelper(20); // 50 是坐标轴的长度
 | 
	
		
			
				|  |  | -  axesHelper.position.set(-100, -100, 0); // 将坐标系指示器放置在左下角
 | 
	
		
			
				|  |  | -  console.log("Axes helper added to scene:", axesHelper); // 调试日志
 | 
	
		
			
				|  |  | -  // 添加标签
 | 
	
		
			
				|  |  | -  const labels = ['X', 'Y', 'Z'];
 | 
	
		
			
				|  |  | -  const colors = [0xff0000, 0x00ff00, 0x0000ff]; // 红、绿、蓝
 | 
	
		
			
				|  |  | -  labels.forEach((label, index) => {
 | 
	
		
			
				|  |  | -    const sprite = new THREE.Sprite(new THREE.SpriteMaterial({ color: colors[index] }));
 | 
	
		
			
				|  |  | -    sprite.position.set(60 * (index === 0 ? 1 : 0), 60 * (index === 1 ? 1 : 0), 60 * (index === 2 ? 1 : 0));
 | 
	
		
			
				|  |  | -    axesHelper.add(sprite);
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -  return axesHelper;
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// 初始化场景
 | 
	
		
			
				|  |  | -const init = () => {
 | 
	
		
			
				|  |  | -  scene = initScene();
 | 
	
		
			
				|  |  | -  camera = initCamera();
 | 
	
		
			
				|  |  | -  renderer = initRenderer(threeContainer.value);
 | 
	
		
			
				|  |  | -  controls = initControls(camera, renderer);
 | 
	
		
			
				|  |  | -   // 初始化 AxesHelper
 | 
	
		
			
				|  |  | -  const { axesHelper, updateAxesHelperPosition } = initAxesHelper(scene, camera, renderer.domElement);
 | 
	
		
			
				|  |  | -  return { updateAxesHelperPosition };
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -const adjustCameraToFit = (scene, camera) => {
 | 
	
		
			
				|  |  | -  const box = new THREE.Box3().setFromObject(scene);
 | 
	
		
			
				|  |  | -  const size = new THREE.Vector3();
 | 
	
		
			
				|  |  | -  box.getSize(size);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  const maxDim = Math.max(size.x, size.y, size.z);
 | 
	
		
			
				|  |  | -  const fov = camera.fov * (Math.PI / 180);
 | 
	
		
			
				|  |  | -  let cameraZ = Math.abs(maxDim / Math.sin(fov / 2));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  const center = new THREE.Vector3();
 | 
	
		
			
				|  |  | -  box.getCenter(center);
 | 
	
		
			
				|  |  | -  camera.position.set(center.x, center.y, cameraZ);
 | 
	
		
			
				|  |  | -  camera.lookAt(center);
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// 渲染 VTK 数据
 | 
	
		
			
				|  |  | -const renderVTK = (vtkData) => {
 | 
	
		
			
				|  |  | -  if (!vtkData) return;
 | 
	
		
			
				|  |  | -  // 根据文件格式选择解析器
 | 
	
		
			
				|  |  | -  const parser = VTKParserFactory.createParser(vtkData.datasetType);
 | 
	
		
			
				|  |  | -  const parsedData = parser.parse(vtkData);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // 根据文件格式选择渲染器
 | 
	
		
			
				|  |  | -  let dataRenderer;
 | 
	
		
			
				|  |  | -  switch (vtkData.datasetType) {
 | 
	
		
			
				|  |  | -    case "UNSTRUCTURED_GRID":
 | 
	
		
			
				|  |  | -      dataRenderer = new UnstructuredGridRenderer();
 | 
	
		
			
				|  |  | -      break;
 | 
	
		
			
				|  |  | -    case "POLYDATA":
 | 
	
		
			
				|  |  | -      dataRenderer = new PolyDataRenderer();
 | 
	
		
			
				|  |  | -      break;
 | 
	
		
			
				|  |  | -    default:
 | 
	
		
			
				|  |  | -      throw new Error(`Unsupported dataset type: ${vtkData.datasetType}`);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // 渲染数据
 | 
	
		
			
				|  |  | -  dataRenderer.render(parsedData, scene);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // 根据数据类型调整相机位置
 | 
	
		
			
				|  |  | -  if (vtkData.datasetType === "UNSTRUCTURED_GRID") {
 | 
	
		
			
				|  |  | -    adjustCameraForUnstructuredGrid(scene, camera);
 | 
	
		
			
				|  |  | -  } else if (vtkData.datasetType === "POLYDATA") {
 | 
	
		
			
				|  |  | -    adjustCameraForPolydata(scene, camera);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // adjustCameraToFit(scene, camera);
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// 监听 vtkData 变化
 | 
	
		
			
				|  |  | -watch(
 | 
	
		
			
				|  |  | -  () => props.vtkData,
 | 
	
		
			
				|  |  | -  (newData) => {
 | 
	
		
			
				|  |  | -    if (newData) {
 | 
	
		
			
				|  |  | -      // 清空场景
 | 
	
		
			
				|  |  | -      while (scene.children.length > 0) {
 | 
	
		
			
				|  |  | -        scene.remove(scene.children[0]);
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      // 重新渲染 VTK 数据
 | 
	
		
			
				|  |  | -      renderVTK(newData);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  },
 | 
	
		
			
				|  |  | -  { immediate: true }
 | 
	
		
			
				|  |  | -);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// VTK 数据
 | 
	
		
			
				|  |  | -onMounted(() => {
 | 
	
		
			
				|  |  | -  const { updateAxesHelperPosition } = init();
 | 
	
		
			
				|  |  | -  animateScene(scene, camera, renderer, controls, () => {
 | 
	
		
			
				|  |  | -    updateAxesHelperPosition(); // 更新 AxesHelper 的位置和方向
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -  // 监听窗口大小变化
 | 
	
		
			
				|  |  | -  window.addEventListener("resize", onWindowResize);
 | 
	
		
			
				|  |  | -});
 | 
	
		
			
				|  |  | -onUnmounted(() => {
 | 
	
		
			
				|  |  | -  // 清理场景
 | 
	
		
			
				|  |  | -  cleanupScene(renderer);
 | 
	
		
			
				|  |  | -  // 移除窗口大小变化监听器
 | 
	
		
			
				|  |  | -  window.removeEventListener("resize", onWindowResize);
 | 
	
		
			
				|  |  | -});
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -const onWindowResize = () => {
 | 
	
		
			
				|  |  | -  const width = threeContainer.value.clientWidth;
 | 
	
		
			
				|  |  | -  const height = threeContainer.value.clientHeight;
 | 
	
		
			
				|  |  | -  camera.aspect = width / height;
 | 
	
		
			
				|  |  | -  camera.updateProjectionMatrix();
 | 
	
		
			
				|  |  | -  renderer.setSize(width, height);
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -const adjustCameraForUnstructuredGrid = (scene, camera) => {
 | 
	
		
			
				|  |  | -  const box = new THREE.Box3().setFromObject(scene);
 | 
	
		
			
				|  |  | -  const size = new THREE.Vector3();
 | 
	
		
			
				|  |  | -  box.getSize(size);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  const maxDim = Math.max(size.x, size.y, size.z);
 | 
	
		
			
				|  |  | -  const fov = camera.fov * (Math.PI / 180);
 | 
	
		
			
				|  |  | -  let cameraZ = Math.abs(maxDim / Math.sin(fov / 2));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  const center = new THREE.Vector3();
 | 
	
		
			
				|  |  | -  box.getCenter(center);
 | 
	
		
			
				|  |  | -  camera.position.set(center.x, center.y, cameraZ);
 | 
	
		
			
				|  |  | -  camera.lookAt(center);
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -const adjustCameraForPolydata = (scene, camera) => {
 | 
	
		
			
				|  |  | -  const box = new THREE.Box3().setFromObject(scene);
 | 
	
		
			
				|  |  | -  // 手动设置边界框
 | 
	
		
			
				|  |  | -  box.set(
 | 
	
		
			
				|  |  | -    new THREE.Vector3(-100, -100, -100),
 | 
	
		
			
				|  |  | -    new THREE.Vector3(100, 100, 100)
 | 
	
		
			
				|  |  | -  );
 | 
	
		
			
				|  |  | -  const size = new THREE.Vector3();
 | 
	
		
			
				|  |  | -  box.getSize(size);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  console.log("Polydata bounding box:", box);
 | 
	
		
			
				|  |  | -  console.log("Polydata size:", size);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  const maxDim = Math.max(size.x, size.y, size.z);
 | 
	
		
			
				|  |  | -  const fov = camera.fov * (Math.PI / 180);
 | 
	
		
			
				|  |  | -  let cameraZ = Math.abs(maxDim / Math.sin(fov / 2));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  const center = new THREE.Vector3();
 | 
	
		
			
				|  |  | -  box.getCenter(center);
 | 
	
		
			
				|  |  | -  camera.position.set(center.x, center.y, cameraZ * 0.8); // 调整相机距离
 | 
	
		
			
				|  |  | -  camera.lookAt(center);
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -</script>
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -<style>
 | 
	
		
			
				|  |  | -.three-container {
 | 
	
		
			
				|  |  | -  width: 100%;
 | 
	
		
			
				|  |  | -  height: calc(89vh - 8px); /* 给容器设置固定高度 */
 | 
	
		
			
				|  |  | -  border: 1px solid #ccc; /* 可选:添加边框以便查看容器范围 */
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -</style>
 |