liuqiao 1 year ago
parent
commit
08023e21e2

+ 236 - 0
Examples/Widgets/Box/BoxWidget.js

@@ -0,0 +1,236 @@
+import macro from '@kitware/vtk.js/macros';
+import vtkAbstractWidgetFactory from '@kitware/vtk.js/Widgets/Core/AbstractWidgetFactory';
+import vtkConvexFaceContextRepresentation from '@kitware/vtk.js/Widgets/Representations/ConvexFaceContextRepresentation';
+import vtkPlaneManipulator from '@kitware/vtk.js/Widgets/Manipulators/PlaneManipulator';
+import vtkSphereHandleRepresentation from '@kitware/vtk.js/Widgets/Representations/SphereHandleRepresentation';
+import vtkStateBuilder from '@kitware/vtk.js/Widgets/Core/StateBuilder';
+
+import { ViewTypes } from '@kitware/vtk.js/Widgets/Core/WidgetManager/Constants';
+
+// ----------------------------------------------------------------------------
+// Widget linked to a view
+// ----------------------------------------------------------------------------
+
+function widgetBehavior(publicAPI, model) {
+  let isDragging = null;
+
+  publicAPI.setDisplayCallback = (callback) =>
+    model.representations[0].setDisplayCallback(callback);
+
+  publicAPI.handleLeftButtonPress = () => {
+    if (
+      !model.activeState ||
+      !model.activeState.getActive() ||
+      !model.pickable
+    ) {
+      return macro.VOID;
+    }
+    isDragging = true;
+    model._interactor.requestAnimation(publicAPI);
+    return macro.EVENT_ABORT;
+  };
+
+  publicAPI.handleMouseMove = (callData) => {
+    if (isDragging && model.pickable) {
+      return publicAPI.handleEvent(callData);
+    }
+    return macro.VOID;
+  };
+
+  publicAPI.handleLeftButtonRelease = () => {
+    if (isDragging && model.pickable) {
+      model._interactor.cancelAnimation(publicAPI);
+    }
+    isDragging = false;
+    model.widgetState.deactivate();
+  };
+
+  publicAPI.handleEvent = (callData) => {
+    if (
+      model.pickable &&
+      model.manipulator &&
+      model.activeState &&
+      model.activeState.getActive()
+    ) {
+      // model.manipulator.setNormal(model.camera.getDirectionOfProjection());
+      const { worldCoords } = model.manipulator.handleEvent(
+        callData,
+        model._apiSpecificRenderWindow
+      );
+
+      if (worldCoords.length) {
+        model.activeState.setOrigin(...worldCoords);
+      }
+      return macro.EVENT_ABORT;
+    }
+    return macro.VOID;
+  };
+
+  // --------------------------------------------------------------------------
+  // initialization
+  // --------------------------------------------------------------------------
+
+  model.camera = model._renderer.getActiveCamera();
+
+  model.classHierarchy.push('vtkBoxWidgetProp');
+}
+
+// ----------------------------------------------------------------------------
+// Factory
+// ----------------------------------------------------------------------------
+
+function vtkBoxWidget(publicAPI, model) {
+  model.classHierarchy.push('vtkBoxWidget');
+
+  // --- Widget Requirement ---------------------------------------------------
+  model.behavior = widgetBehavior;
+
+  model.methodsToLink = ['scaleInPixels'];
+  publicAPI.getRepresentationsForViewType = (viewType) => {
+    switch (viewType) {
+      case ViewTypes.DEFAULT:
+      case ViewTypes.GEOMETRY:
+      case ViewTypes.SLICE:
+      case ViewTypes.VOLUME:
+      default:
+        return [
+          { builder: vtkSphereHandleRepresentation, labels: ['handles'] },
+          {
+            builder: vtkConvexFaceContextRepresentation,
+            labels: ['---', '--+', '-++', '-+-'],
+          },
+          {
+            builder: vtkConvexFaceContextRepresentation,
+            labels: ['---', '+--', '+-+', '--+'],
+          },
+          {
+            builder: vtkConvexFaceContextRepresentation,
+            labels: ['+--', '++-', '+++', '+-+'],
+          },
+          {
+            builder: vtkConvexFaceContextRepresentation,
+            labels: ['++-', '-+-', '-++', '+++'],
+          },
+          {
+            builder: vtkConvexFaceContextRepresentation,
+            labels: ['--+', '+-+', '+++', '-++'],
+          },
+          {
+            builder: vtkConvexFaceContextRepresentation,
+            labels: ['---', '+--', '++-', '-+-'],
+          },
+        ];
+    }
+  };
+  // --- Widget Requirement ---------------------------------------------------
+
+  // Default state
+  model.widgetState = vtkStateBuilder
+    .createBuilder()
+    .addStateFromMixin({
+      labels: ['handles', '---'],
+      mixins: ['origin', 'color', 'scale1', 'manipulator'],
+      name: 'handle',
+      initialValues: {
+        scale1: 0.1,
+        origin: [-1, -1, -1],
+      },
+    })
+    .addStateFromMixin({
+      labels: ['handles', '-+-'],
+      mixins: ['origin', 'color', 'scale1', 'manipulator'],
+      name: 'handle',
+      initialValues: {
+        scale1: 0.1,
+        origin: [-1, 1, -1],
+      },
+    })
+    .addStateFromMixin({
+      labels: ['handles', '+--'],
+      mixins: ['origin', 'color', 'scale1', 'manipulator'],
+      name: 'handle',
+      initialValues: {
+        scale1: 0.1,
+        origin: [1, -1, -1],
+      },
+    })
+    .addStateFromMixin({
+      labels: ['handles', '++-'],
+      mixins: ['origin', 'color', 'scale1', 'manipulator'],
+      name: 'handle',
+      initialValues: {
+        scale1: 0.1,
+        origin: [1, 1, -1],
+      },
+    })
+    .addStateFromMixin({
+      labels: ['handles', '--+'],
+      mixins: ['origin', 'color', 'scale1', 'manipulator'],
+      name: 'handle',
+      initialValues: {
+        scale1: 0.1,
+        origin: [-1, -1, 1],
+      },
+    })
+    .addStateFromMixin({
+      labels: ['handles', '-++'],
+      mixins: ['origin', 'color', 'scale1', 'manipulator'],
+      name: 'handle',
+      initialValues: {
+        scale1: 0.1,
+        origin: [-1, 1, 1],
+      },
+    })
+    .addStateFromMixin({
+      labels: ['handles', '+-+'],
+      mixins: ['origin', 'color', 'scale1', 'manipulator'],
+      name: 'handle',
+      initialValues: {
+        scale1: 0.1,
+        origin: [1, -1, 1],
+      },
+    })
+    .addStateFromMixin({
+      labels: ['handles', '+++'],
+      mixins: ['origin', 'color', 'scale1', 'manipulator'],
+      name: 'handle',
+      initialValues: {
+        scale1: 0.1,
+        origin: [1, 1, 1],
+      },
+    })
+    .build();
+  const handles = model.widgetState.getStatesWithLabel('handles');
+
+  // Default manipulator
+  model.manipulator = vtkPlaneManipulator.newInstance({
+    useCameraNormal: true,
+  });
+  handles.forEach((handle) => handle.setManipulator(model.manipulator));
+}
+
+// ----------------------------------------------------------------------------
+
+const DEFAULT_VALUES = {
+  manipulator: null,
+};
+
+// ----------------------------------------------------------------------------
+
+export function extend(publicAPI, model, initialValues = {}) {
+  Object.assign(model, DEFAULT_VALUES, initialValues);
+
+  vtkAbstractWidgetFactory.extend(publicAPI, model, initialValues);
+
+  macro.setGet(publicAPI, model, ['manipulator']);
+
+  vtkBoxWidget(publicAPI, model);
+}
+
+// ----------------------------------------------------------------------------
+
+export const newInstance = macro.newInstance(extend, 'vtkBoxWidget');
+
+// ----------------------------------------------------------------------------
+
+export default { newInstance, extend };

+ 34 - 0
Examples/Widgets/Box/controlPanel.html

@@ -0,0 +1,34 @@
+<table>
+  <tr>
+    <td>pickable</td>
+    <td>
+      <input class='flag' data-name="pickable" type="checkbox" checked />
+    </td>
+  </tr>
+  <tr>
+    <td>visibility</td>
+    <td>
+      <input class='flag' data-name="visibility" type="checkbox" checked />
+    </td>
+  </tr>
+  <tr>
+    <td>contextVisibility</td>
+    <td>
+      <input class='flag' data-name="contextVisibility" type="checkbox" checked />
+    </td>
+  </tr>
+  <tr>
+    <td>handleVisibility</td>
+    <td>
+      <input class='flag' data-name="handleVisibility" type="checkbox" checked />
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <button data-action="addWidget">Add</button>
+    </td>
+    <td>
+      <button data-action="removeWidget">Remove</button>
+    </td>
+  </tr>
+</table>

+ 104 - 0
Examples/Widgets/Box/index.js

@@ -0,0 +1,104 @@
+import '@kitware/vtk.js/favicon';
+
+// Load the rendering pieces we want to use (for both WebGL and WebGPU)
+import '@kitware/vtk.js/Rendering/Profiles/Geometry';
+import '@kitware/vtk.js/Rendering/Profiles/Glyph';
+
+import vtkFullScreenRenderWindow from '@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow';
+import vtkWidgetManager from '@kitware/vtk.js/Widgets/Core/WidgetManager';
+
+import vtkBoxWidget from './BoxWidget';
+import controlPanel from './controlPanel.html';
+
+// ----------------------------------------------------------------------------
+// Standard rendering code setup
+// ----------------------------------------------------------------------------
+
+const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({
+  background: [0, 0, 0],
+});
+const renderer = fullScreenRenderer.getRenderer();
+const renderWindow = fullScreenRenderer.getRenderWindow();
+const openGLRenderWindow = fullScreenRenderer.getApiSpecificRenderWindow();
+
+// ----------------------------------------------------------------------------
+// 2D overlay rendering
+// ----------------------------------------------------------------------------
+
+const overlaySize = 15;
+const overlayBorder = 2;
+const overlay = document.createElement('div');
+overlay.style.position = 'absolute';
+overlay.style.width = `${overlaySize}px`;
+overlay.style.height = `${overlaySize}px`;
+overlay.style.border = `solid ${overlayBorder}px red`;
+overlay.style.borderRadius = '50%';
+overlay.style.left = '-100px';
+overlay.style.pointerEvents = 'none';
+document.querySelector('body').appendChild(overlay);
+
+// ----------------------------------------------------------------------------
+// Widget manager
+// ----------------------------------------------------------------------------
+
+const widgetManager = vtkWidgetManager.newInstance();
+widgetManager.setRenderer(renderer);
+
+const widget = vtkBoxWidget.newInstance();
+
+function widgetRegistration(e) {
+  const action = e ? e.currentTarget.dataset.action : 'addWidget';
+  const viewWidget = widgetManager[action](widget);
+  if (viewWidget) {
+    viewWidget.setScaleInPixels(false);
+    viewWidget.setDisplayCallback((coords) => {
+      overlay.style.left = '-100px';
+      if (coords) {
+        const [w, h] = openGLRenderWindow.getSize();
+        overlay.style.left = `${Math.round(
+          (coords[0][0] / w) * window.innerWidth -
+            overlaySize * 0.5 -
+            overlayBorder
+        )}px`;
+        overlay.style.top = `${Math.round(
+          ((h - coords[0][1]) / h) * window.innerHeight -
+            overlaySize * 0.5 -
+            overlayBorder
+        )}px`;
+      }
+    });
+
+    renderer.resetCamera();
+    renderer.resetCameraClippingRange();
+  }
+  widgetManager.enablePicking();
+  renderWindow.render();
+}
+
+// Initial widget register
+widgetRegistration();
+
+// -----------------------------------------------------------
+// UI control handling
+// -----------------------------------------------------------
+
+fullScreenRenderer.addController(controlPanel);
+
+function updateFlag(e) {
+  const value = !!e.target.checked;
+  const name = e.currentTarget.dataset.name;
+  widget.set({ [name]: value }); // can be called on either viewWidget or parentWidget
+
+  widgetManager.enablePicking();
+  renderWindow.render();
+}
+
+const elems = document.querySelectorAll('.flag');
+for (let i = 0; i < elems.length; i++) {
+  elems[i].addEventListener('change', updateFlag);
+}
+
+const buttons = document.querySelectorAll('button');
+for (let i = 0; i < buttons.length; i++) {
+  buttons[i].addEventListener('click', widgetRegistration);
+}

+ 210 - 0
Examples/Widgets/Utilities/SVGHelpers.js

@@ -0,0 +1,210 @@
+import {
+  init,
+  classModule,
+  propsModule,
+  styleModule,
+  eventListenersModule,
+  h,
+  attributesModule,
+} from 'snabbdom';
+
+const patch = init([
+  attributesModule,
+  classModule,
+  propsModule,
+  styleModule,
+  eventListenersModule,
+]);
+
+function mountDummySVGContainer(canvas) {
+  const container = canvas.parentElement;
+
+  const dummy = document.createElement('div');
+  container.insertBefore(dummy, canvas.nextSibling);
+
+  const containerStyles = window.getComputedStyle(container);
+  if (containerStyles.position === 'static') {
+    container.style.position = 'relative';
+  }
+
+  return dummy;
+}
+
+export const VerticalTextAlignment = {
+  TOP: 1,
+  MIDDLE: 2,
+  BOTTOM: 3,
+};
+
+/**
+ * Computes the relative dy values around 0 for multiline text.
+ *
+ * @param nLines
+ * @param fontSize
+ * @returns a list of vertical offsets (from a zero origin) for placing multiline text.
+ */
+export function multiLineTextCalculator(
+  nLines,
+  fontSize,
+  alignment = VerticalTextAlignment.BOTTOM
+) {
+  const dys = [];
+  for (let i = 0; i < nLines; i++) {
+    switch (alignment) {
+      case VerticalTextAlignment.TOP:
+        dys.push(fontSize * (i + 1));
+        break;
+      case VerticalTextAlignment.MIDDLE:
+        dys.push(-fontSize * (0.5 * nLines - i - 1));
+        break;
+      case VerticalTextAlignment.BOTTOM:
+      default:
+        dys.push(-fontSize * (nLines - i - 1));
+    }
+  }
+  return dys;
+}
+
+/**
+ * Automatically updates an SVG rendering whenever a widget's state is updated.
+ *
+ * This update is done in two phases:
+ * 1. mapState(widgetState) takes the widget state and transforms it into an intermediate data representation.
+ * 2. render(data, h) takes the intermediate data representation and a createElement `h` function, and returns
+ *    an SVG rendering of the state encoded in `data`.
+ *
+ * See snabbdom's documentation for how to use the `h` function passed to `render()`.
+ *
+ * @param renderer the widget manager's renderer
+ * @param widgetState the widget state
+ * @param mapState (object parameter) transforms the given widget's state into an intermediate data representation to be passed to render().
+ * @param render (object parameter) returns the SVG representation given the data from mapState() and snabbdom's h render function.
+ */
+export function bindSVGRepresentation(
+  renderer,
+  widgetState,
+  { mapState, render }
+) {
+  const view = renderer.getRenderWindow().getViews()[0];
+  const canvas = view.getCanvas();
+
+  const getSize = () => {
+    const [width, height] = view.getSize();
+    const ratio = window.devicePixelRatio || 1;
+    return {
+      width: width / ratio,
+      height: height / ratio,
+      viewBox: `0 0 ${width} ${height}`,
+    };
+  };
+
+  const renderState = (state) => {
+    const repData = mapState(state, {
+      size: view.getSize(),
+    });
+    const rendered = render(repData, h);
+    return h(
+      'svg',
+      {
+        attrs: getSize(),
+        style: {
+          position: 'absolute',
+          top: '0',
+          left: '0',
+          width: '100%',
+          height: '100%',
+          // deny pointer events by default
+          'pointer-events': 'none',
+        },
+      },
+      Array.isArray(rendered) ? rendered : [rendered]
+    );
+  };
+
+  const dummy = mountDummySVGContainer(canvas);
+  let vnode = patch(dummy, renderState(widgetState));
+
+  const updateVNode = () => {
+    vnode = patch(vnode, renderState(widgetState));
+  };
+
+  const stateSub = widgetState.onModified(() => updateVNode());
+  const cameraSub = renderer.getActiveCamera().onModified(() => updateVNode());
+  const observer = new ResizeObserver(() => updateVNode());
+  observer.observe(canvas);
+
+  return () => {
+    stateSub.unsubscribe();
+    cameraSub.unsubscribe();
+    observer.disconnect();
+    patch(vnode, h('!')); // unmount hack
+    vnode = null;
+  };
+}
+
+/**
+ * Applies a set of default interaction handling behavior.
+ *
+ * Typically, firing pointerenter means that the pointer is
+ * "hovering", meaning the associated widget state should
+ * be selected. (This is on the user to do this step.)
+ * Accordingly, pointerleave means no more hovering.
+ *
+ * However, vtk.js captures the pointer on pointerdown,
+ * which means that clicking on an SVG element will result
+ * in a pointerleave being triggered, deselecting the
+ * widget state.
+ *
+ * The abridged sequence of events is as follows:
+ * 1. pointerenter on the SVG element (mouse moves over SVG handle)
+ * 2. pointerdown on the SVG element (left button press)
+ * 2. pointerdown on the vtk.js canvas (left button press)
+ * 3. pointer captured on the vtk.js canvas (left button press)
+ * 4. pointerleave on the SVG element as soon as the mouse is moved,
+ *    since the capture target is now the canvas.
+ * 5. pointerenter on the SVG element when the mouse/pointer is released.
+ *
+ * To workaround this issue, we conditionally fire the user's
+ * pointerleave listener only when we are "locked", which means
+ * we saw a pointerdown and so the vtk.js canvas is capturing
+ * the current pointer.
+ */
+function applyDefaultInteractions(userListeners) {
+  let locked = false;
+  return {
+    ...userListeners,
+    pointerdown(ev) {
+      locked = true;
+      return userListeners?.pointerdown?.(ev);
+    },
+    pointerenter(ev) {
+      if (locked) {
+        locked = false;
+      }
+      return userListeners?.pointerenter?.(ev);
+    },
+    pointerleave(ev) {
+      if (!locked) {
+        return userListeners?.pointerleave?.(ev);
+      }
+      return undefined;
+    },
+  };
+}
+
+/**
+ * Requires the snabbdom eventlisteners and style modules.
+ * @param vnode
+ * @returns
+ */
+export function makeListenableSVGNode(vnode) {
+  // allow pointer events on this vnode
+  vnode.data.style = {
+    ...vnode.data.style,
+    'pointer-events': 'all',
+  };
+  vnode.data.on = applyDefaultInteractions(vnode.data.on);
+  return vnode;
+}
+
+export default { bindSVGRepresentation, multiLineTextCalculator };

+ 339 - 68
package-lock.json

@@ -11,6 +11,7 @@
         "@element-plus/icons-vue": "^2.1.0",
         "@kitware/vtk.js": "^29.7.3",
         "axios": "^1.5.0",
+        "deep-equal": "^2.2.3",
         "echarts": "^5.4.3",
         "element-plus": "^2.3.14",
         "jquery": "^3.7.1",
@@ -21,7 +22,9 @@
         "pinia-plugin-persistedstate": "^3.2.0",
         "sass": "^1.71.1",
         "sass-loader": "^13.3.3",
+        "snabbdom": "^3.6.2",
         "v-scale-screen": "^2.2.0",
+        "vtk.js": "^31.0.0",
         "vue": "^3.3.4",
         "vue-router": "4.0",
         "webuploader": "^0.1.8"
@@ -3401,7 +3404,6 @@
       "version": "1.0.0",
       "resolved": "https://registry.npmmirror.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
       "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
-      "dev": true,
       "dependencies": {
         "call-bind": "^1.0.2",
         "is-array-buffer": "^3.0.1"
@@ -3530,12 +3532,17 @@
       }
     },
     "node_modules/available-typed-arrays": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmmirror.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
-      "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
-      "dev": true,
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+      "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+      "dependencies": {
+        "possible-typed-array-names": "^1.0.0"
+      },
       "engines": {
         "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
       }
     },
     "node_modules/axios": {
@@ -3677,13 +3684,21 @@
       }
     },
     "node_modules/call-bind": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.2.tgz",
-      "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
-      "dev": true,
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
+      "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
       "dependencies": {
-        "function-bind": "^1.1.1",
-        "get-intrinsic": "^1.0.2"
+        "es-define-property": "^1.0.0",
+        "es-errors": "^1.3.0",
+        "function-bind": "^1.1.2",
+        "get-intrinsic": "^1.2.4",
+        "set-function-length": "^1.2.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
       }
     },
     "node_modules/callsites": {
@@ -3942,6 +3957,37 @@
         }
       }
     },
+    "node_modules/deep-equal": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz",
+      "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==",
+      "dependencies": {
+        "array-buffer-byte-length": "^1.0.0",
+        "call-bind": "^1.0.5",
+        "es-get-iterator": "^1.1.3",
+        "get-intrinsic": "^1.2.2",
+        "is-arguments": "^1.1.1",
+        "is-array-buffer": "^3.0.2",
+        "is-date-object": "^1.0.5",
+        "is-regex": "^1.1.4",
+        "is-shared-array-buffer": "^1.0.2",
+        "isarray": "^2.0.5",
+        "object-is": "^1.1.5",
+        "object-keys": "^1.1.1",
+        "object.assign": "^4.1.4",
+        "regexp.prototype.flags": "^1.5.1",
+        "side-channel": "^1.0.4",
+        "which-boxed-primitive": "^1.0.2",
+        "which-collection": "^1.0.1",
+        "which-typed-array": "^1.1.13"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/deep-is": {
       "version": "0.1.4",
       "resolved": "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz",
@@ -3949,16 +3995,19 @@
       "dev": true
     },
     "node_modules/define-data-property": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.0.tgz",
-      "integrity": "sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==",
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+      "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
       "dependencies": {
-        "get-intrinsic": "^1.2.1",
-        "gopd": "^1.0.1",
-        "has-property-descriptors": "^1.0.0"
+        "es-define-property": "^1.0.0",
+        "es-errors": "^1.3.0",
+        "gopd": "^1.0.1"
       },
       "engines": {
         "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
       }
     },
     "node_modules/define-properties": {
@@ -4117,6 +4166,44 @@
         "node": ">= 0.4"
       }
     },
+    "node_modules/es-define-property": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
+      "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
+      "dependencies": {
+        "get-intrinsic": "^1.2.4"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-errors": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+      "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-get-iterator": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz",
+      "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==",
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "get-intrinsic": "^1.1.3",
+        "has-symbols": "^1.0.3",
+        "is-arguments": "^1.1.1",
+        "is-map": "^2.0.2",
+        "is-set": "^2.0.2",
+        "is-string": "^1.0.7",
+        "isarray": "^2.0.5",
+        "stop-iteration-iterator": "^1.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/es-module-lexer": {
       "version": "1.4.1",
       "resolved": "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-1.4.1.tgz",
@@ -4781,7 +4868,6 @@
       "version": "0.3.3",
       "resolved": "https://registry.npmmirror.com/for-each/-/for-each-0.3.3.tgz",
       "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
-      "dev": true,
       "dependencies": {
         "is-callable": "^1.1.3"
       }
@@ -4827,9 +4913,12 @@
       }
     },
     "node_modules/function-bind": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz",
-      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
     },
     "node_modules/function.prototype.name": {
       "version": "1.1.6",
@@ -4849,8 +4938,7 @@
     "node_modules/functions-have-names": {
       "version": "1.2.3",
       "resolved": "https://registry.npmmirror.com/functions-have-names/-/functions-have-names-1.2.3.tgz",
-      "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
-      "dev": true
+      "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="
     },
     "node_modules/gensync": {
       "version": "1.0.0-beta.2",
@@ -4862,14 +4950,21 @@
       }
     },
     "node_modules/get-intrinsic": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
-      "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==",
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
+      "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
       "dependencies": {
-        "function-bind": "^1.1.1",
-        "has": "^1.0.3",
+        "es-errors": "^1.3.0",
+        "function-bind": "^1.1.2",
         "has-proto": "^1.0.1",
-        "has-symbols": "^1.0.3"
+        "has-symbols": "^1.0.3",
+        "hasown": "^2.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
       }
     },
     "node_modules/get-symbol-description": {
@@ -5027,8 +5122,7 @@
     "node_modules/has-bigints": {
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/has-bigints/-/has-bigints-1.0.2.tgz",
-      "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
-      "dev": true
+      "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ=="
     },
     "node_modules/has-flag": {
       "version": "4.0.0",
@@ -5039,11 +5133,14 @@
       }
     },
     "node_modules/has-property-descriptors": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
-      "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+      "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
       "dependencies": {
-        "get-intrinsic": "^1.1.1"
+        "es-define-property": "^1.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
       }
     },
     "node_modules/has-proto": {
@@ -5063,12 +5160,25 @@
       }
     },
     "node_modules/has-tostringtag": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
-      "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
-      "dev": true,
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+      "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
       "dependencies": {
-        "has-symbols": "^1.0.2"
+        "has-symbols": "^1.0.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/hasown": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+      "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+      "dependencies": {
+        "function-bind": "^1.1.2"
       },
       "engines": {
         "node": ">= 0.4"
@@ -5137,7 +5247,6 @@
       "version": "1.0.5",
       "resolved": "https://registry.npmmirror.com/internal-slot/-/internal-slot-1.0.5.tgz",
       "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==",
-      "dev": true,
       "dependencies": {
         "get-intrinsic": "^1.2.0",
         "has": "^1.0.3",
@@ -5163,11 +5272,25 @@
         "node": ">= 0.10"
       }
     },
+    "node_modules/is-arguments": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
+      "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "has-tostringtag": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/is-array-buffer": {
       "version": "3.0.2",
       "resolved": "https://registry.npmmirror.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
       "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
-      "dev": true,
       "dependencies": {
         "call-bind": "^1.0.2",
         "get-intrinsic": "^1.2.0",
@@ -5178,7 +5301,6 @@
       "version": "1.0.4",
       "resolved": "https://registry.npmmirror.com/is-bigint/-/is-bigint-1.0.4.tgz",
       "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
-      "dev": true,
       "dependencies": {
         "has-bigints": "^1.0.1"
       }
@@ -5198,7 +5320,6 @@
       "version": "1.1.2",
       "resolved": "https://registry.npmmirror.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
       "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
-      "dev": true,
       "dependencies": {
         "call-bind": "^1.0.2",
         "has-tostringtag": "^1.0.0"
@@ -5211,7 +5332,6 @@
       "version": "1.2.7",
       "resolved": "https://registry.npmmirror.com/is-callable/-/is-callable-1.2.7.tgz",
       "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
-      "dev": true,
       "engines": {
         "node": ">= 0.4"
       }
@@ -5228,7 +5348,6 @@
       "version": "1.0.5",
       "resolved": "https://registry.npmmirror.com/is-date-object/-/is-date-object-1.0.5.tgz",
       "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
-      "dev": true,
       "dependencies": {
         "has-tostringtag": "^1.0.0"
       },
@@ -5255,6 +5374,17 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/is-map": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
+      "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/is-negative-zero": {
       "version": "2.0.2",
       "resolved": "https://registry.npmmirror.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
@@ -5276,7 +5406,6 @@
       "version": "1.0.7",
       "resolved": "https://registry.npmmirror.com/is-number-object/-/is-number-object-1.0.7.tgz",
       "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
-      "dev": true,
       "dependencies": {
         "has-tostringtag": "^1.0.0"
       },
@@ -5297,7 +5426,6 @@
       "version": "1.1.4",
       "resolved": "https://registry.npmmirror.com/is-regex/-/is-regex-1.1.4.tgz",
       "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
-      "dev": true,
       "dependencies": {
         "call-bind": "^1.0.2",
         "has-tostringtag": "^1.0.0"
@@ -5306,11 +5434,21 @@
         "node": ">= 0.4"
       }
     },
+    "node_modules/is-set": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
+      "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/is-shared-array-buffer": {
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
       "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
-      "dev": true,
       "dependencies": {
         "call-bind": "^1.0.2"
       }
@@ -5319,7 +5457,6 @@
       "version": "1.0.7",
       "resolved": "https://registry.npmmirror.com/is-string/-/is-string-1.0.7.tgz",
       "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
-      "dev": true,
       "dependencies": {
         "has-tostringtag": "^1.0.0"
       },
@@ -5331,7 +5468,6 @@
       "version": "1.0.4",
       "resolved": "https://registry.npmmirror.com/is-symbol/-/is-symbol-1.0.4.tgz",
       "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
-      "dev": true,
       "dependencies": {
         "has-symbols": "^1.0.2"
       },
@@ -5343,7 +5479,6 @@
       "version": "1.1.12",
       "resolved": "https://registry.npmmirror.com/is-typed-array/-/is-typed-array-1.1.12.tgz",
       "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==",
-      "dev": true,
       "dependencies": {
         "which-typed-array": "^1.1.11"
       },
@@ -5351,6 +5486,17 @@
         "node": ">= 0.4"
       }
     },
+    "node_modules/is-weakmap": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
+      "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/is-weakref": {
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/is-weakref/-/is-weakref-1.0.2.tgz",
@@ -5360,11 +5506,25 @@
         "call-bind": "^1.0.2"
       }
     },
+    "node_modules/is-weakset": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz",
+      "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==",
+      "dependencies": {
+        "call-bind": "^1.0.7",
+        "get-intrinsic": "^1.2.4"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/isarray": {
       "version": "2.0.5",
       "resolved": "https://registry.npmmirror.com/isarray/-/isarray-2.0.5.tgz",
-      "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
-      "dev": true
+      "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="
     },
     "node_modules/isexe": {
       "version": "2.0.0",
@@ -5762,8 +5922,22 @@
     "node_modules/object-inspect": {
       "version": "1.12.3",
       "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.12.3.tgz",
-      "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
-      "dev": true
+      "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g=="
+    },
+    "node_modules/object-is": {
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
+      "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==",
+      "dependencies": {
+        "call-bind": "^1.0.7",
+        "define-properties": "^1.2.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
     },
     "node_modules/object-keys": {
       "version": "1.1.1",
@@ -5777,7 +5951,6 @@
       "version": "4.1.4",
       "resolved": "https://registry.npmmirror.com/object.assign/-/object.assign-4.1.4.tgz",
       "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
-      "dev": true,
       "dependencies": {
         "call-bind": "^1.0.2",
         "define-properties": "^1.1.4",
@@ -6020,6 +6193,14 @@
         "pathe": "^1.1.0"
       }
     },
+    "node_modules/possible-typed-array-names": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
+      "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
     "node_modules/postcss": {
       "version": "8.4.30",
       "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.30.tgz",
@@ -6172,7 +6353,6 @@
       "version": "1.5.1",
       "resolved": "https://registry.npmmirror.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz",
       "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==",
-      "dev": true,
       "dependencies": {
         "call-bind": "^1.0.2",
         "define-properties": "^1.2.0",
@@ -6434,11 +6614,26 @@
         "randombytes": "^2.1.0"
       }
     },
+    "node_modules/set-function-length": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+      "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+      "dependencies": {
+        "define-data-property": "^1.1.4",
+        "es-errors": "^1.3.0",
+        "function-bind": "^1.1.2",
+        "get-intrinsic": "^1.2.4",
+        "gopd": "^1.0.1",
+        "has-property-descriptors": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
     "node_modules/set-function-name": {
       "version": "2.0.1",
       "resolved": "https://registry.npmmirror.com/set-function-name/-/set-function-name-2.0.1.tgz",
       "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==",
-      "dev": true,
       "dependencies": {
         "define-data-property": "^1.0.1",
         "functions-have-names": "^1.2.3",
@@ -6497,7 +6692,6 @@
       "version": "1.0.4",
       "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.4.tgz",
       "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
-      "dev": true,
       "dependencies": {
         "call-bind": "^1.0.0",
         "get-intrinsic": "^1.0.2",
@@ -6513,6 +6707,14 @@
         "node": ">=8"
       }
     },
+    "node_modules/snabbdom": {
+      "version": "3.6.2",
+      "resolved": "https://registry.npmjs.org/snabbdom/-/snabbdom-3.6.2.tgz",
+      "integrity": "sha512-ig5qOnCDbugFntKi6c7Xlib8bA6xiJVk8O+WdFrV3wxbMqeHO0hXFQC4nAhPVWfZfi8255lcZkNhtIBINCc4+Q==",
+      "engines": {
+        "node": ">=12.17.0"
+      }
+    },
     "node_modules/source-map": {
       "version": "0.6.1",
       "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz",
@@ -6557,6 +6759,17 @@
       "resolved": "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.0.3.tgz",
       "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
     },
+    "node_modules/stop-iteration-iterator": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz",
+      "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==",
+      "dependencies": {
+        "internal-slot": "^1.0.4"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
     "node_modules/stream-browserify": {
       "version": "3.0.0",
       "resolved": "https://registry.npmmirror.com/stream-browserify/-/stream-browserify-3.0.0.tgz",
@@ -7153,6 +7366,46 @@
         "sourcemap-codec": "^1.4.8"
       }
     },
+    "node_modules/vtk.js": {
+      "version": "31.0.0",
+      "resolved": "https://registry.npmjs.org/vtk.js/-/vtk.js-31.0.0.tgz",
+      "integrity": "sha512-9JlMpjMcG92Wg/e4DF3f5KuC/rnPIa30kW2JuOwtLSGb3s+32Bn141MVE9L0q24YW34cPwP46zxggnQTRQPa+g==",
+      "dependencies": {
+        "@babel/runtime": "7.22.11",
+        "@types/webxr": "^0.5.5",
+        "commander": "9.2.0",
+        "d3-scale": "4.0.2",
+        "fast-deep-equal": "^3.1.3",
+        "fflate": "0.7.3",
+        "gl-matrix": "3.4.3",
+        "globalthis": "1.0.3",
+        "seedrandom": "3.0.5",
+        "shader-loader": "1.3.1",
+        "shelljs": "0.8.5",
+        "spark-md5": "3.0.2",
+        "stream-browserify": "3.0.0",
+        "webworker-promise": "0.5.0",
+        "worker-loader": "3.0.8",
+        "xmlbuilder2": "3.0.2"
+      },
+      "bin": {
+        "vtkDataConverter": "Utilities/DataGenerator/convert-cli.js",
+        "xml2json": "Utilities/XMLConverter/xml2json-cli.js"
+      },
+      "peerDependencies": {
+        "@babel/preset-env": "^7.17.10",
+        "autoprefixer": "^10.4.7",
+        "wslink": ">=1.1.0 || ^2.0.0"
+      }
+    },
+    "node_modules/vtk.js/node_modules/commander": {
+      "version": "9.2.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-9.2.0.tgz",
+      "integrity": "sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w==",
+      "engines": {
+        "node": "^12.20.0 || >=14"
+      }
+    },
     "node_modules/vue": {
       "version": "3.3.4",
       "resolved": "https://registry.npmmirror.com/vue/-/vue-3.3.4.tgz",
@@ -7348,7 +7601,6 @@
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
       "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
-      "dev": true,
       "dependencies": {
         "is-bigint": "^1.0.1",
         "is-boolean-object": "^1.1.0",
@@ -7357,20 +7609,39 @@
         "is-symbol": "^1.0.3"
       }
     },
+    "node_modules/which-collection": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
+      "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
+      "dependencies": {
+        "is-map": "^2.0.3",
+        "is-set": "^2.0.3",
+        "is-weakmap": "^2.0.2",
+        "is-weakset": "^2.0.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/which-typed-array": {
-      "version": "1.1.11",
-      "resolved": "https://registry.npmmirror.com/which-typed-array/-/which-typed-array-1.1.11.tgz",
-      "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==",
-      "dev": true,
+      "version": "1.1.15",
+      "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz",
+      "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==",
       "dependencies": {
-        "available-typed-arrays": "^1.0.5",
-        "call-bind": "^1.0.2",
+        "available-typed-arrays": "^1.0.7",
+        "call-bind": "^1.0.7",
         "for-each": "^0.3.3",
         "gopd": "^1.0.1",
-        "has-tostringtag": "^1.0.0"
+        "has-tostringtag": "^1.0.2"
       },
       "engines": {
         "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
       }
     },
     "node_modules/worker-loader": {

+ 3 - 0
package.json

@@ -14,6 +14,7 @@
     "@element-plus/icons-vue": "^2.1.0",
     "@kitware/vtk.js": "^29.7.3",
     "axios": "^1.5.0",
+    "deep-equal": "^2.2.3",
     "echarts": "^5.4.3",
     "element-plus": "^2.3.14",
     "jquery": "^3.7.1",
@@ -24,7 +25,9 @@
     "pinia-plugin-persistedstate": "^3.2.0",
     "sass": "^1.71.1",
     "sass-loader": "^13.3.3",
+    "snabbdom": "^3.6.2",
     "v-scale-screen": "^2.2.0",
+    "vtk.js": "^31.0.0",
     "vue": "^3.3.4",
     "vue-router": "4.0",
     "webuploader": "^0.1.8"

+ 18 - 1
src/router/index.js

@@ -19,7 +19,24 @@ const router = createRouter({
             },
            
         },
-        
+        {
+          path: '/vtk',
+          name:'案例',
+          component: () => import('@/view/vtk/vtk.vue'),// 这是路由的籁加载,也可以其他方式
+         
+      },
+      {
+        path: '/vtk2',
+        name:'案例1',
+        component: () => import('@/view/vtk/vtk2.vue'),// 这是路由的籁加载,也可以其他方式
+       
+    },
+    {
+      path: '/demo',
+      name:'案例3',
+      component: () => import('@/view/vtk/demo.vue'),// 这是路由的籁加载,也可以其他方式
+     
+  },
         // {
         //     path: '/',
         //     name:'首页',

+ 4 - 0
src/view/appmian.vue

@@ -369,6 +369,10 @@ const handleSelect = (key) => {
     boundary.value.accident4(key);
     sourcedis.value.accident3(key);
     lliudialog.value.accident2(key);
+    // console.log('+model')
+    // console.log( lliudialog.value);
+    // lliudialog.value.dialog.dialogVisible_fire=false;
+   
       break;
     case "5":
 

+ 5 - 0
src/view/components/InfoVtkmodel.vue

@@ -113,3 +113,8 @@ span {
   top: 2px;
 }
 </style>
+<style>
+.vtkmodel1 canvas{
+  background-color: rgba(51,51,51,0.7);
+}
+</style>

+ 73 - 0
src/view/vtk/controlPanel.vue

@@ -0,0 +1,73 @@
+<template>
+  <div>
+  试试
+
+
+<div>
+  <button id="addWidget">Add widget</button> 
+  <br />
+  <button id="removeWidget">Remove widget</button> 
+  <br />
+  <br />
+  <div>Distance: <span id="distance">0</span></div>
+  <br />
+  <div>Text:</div>
+  <textarea id="txtIpt" name="name"></textarea>
+  <br />
+  <br />
+  <div>Line position</div>
+  <input
+    title="Line position"
+    id="linePos"
+    type="range"
+    min="0"
+    max="100"
+    step="1"
+    value="50"
+  />
+  <br />
+
+  <br />
+  <label for="pet-select">Handle1</label>
+  <br />
+
+  <select name="handle1" class="HandleSource" id="idh1">
+    <option value="sphere">Sphere</option>
+    <option value="cone">Cone</option>
+    <option value="cube">Cube</option>
+    <option value="triangle">Triangle</option>
+    <option value="4pointsArrowHead">4 points arrow head</option>
+    <option value="6pointsArrowHead">6 points arrow head</option>
+    <option value="star">Star</option>
+    <option value="disk">Disk</option>
+    <option value="circle">Circle</option>
+    <option value="viewFinder">View Finder</option>
+    <option value="voidSphere">None</option>
+  </select>
+  <div>Visibility
+    <input id="visiH1" type="checkbox" />
+    <br />
+  </div>
+  <br />
+  <label for="pet-select">Handle2</label>
+  <br />
+  <select name="handle2" class="HandleSource" id="idh2">
+    <option value="sphere">Sphere</option>
+    <option value="cone">Cone</option>
+    <option value="cube">Cube</option>
+    <option value="triangle">Triangle</option>
+    <option value="4pointsArrowHead">4 points arrow head</option>
+    <option value="6pointsArrowHead">6 points arrow head</option>
+    <option value="star">Star</option>
+    <option value="disk">Disk</option>
+    <option value="circle">Circle</option>
+    <option value="viewFinder">View Finder</option>
+    <option value="voidSphere">None</option>
+  </select>
+  <div>Visibility
+    <input id="visiH2" type="checkbox" />
+    <br />
+  </div>
+</div>
+</div>
+</template>

+ 10 - 0
src/view/vtk/demo.vue

@@ -0,0 +1,10 @@
+<template>
+    <div>
+    试试
+ </div>
+  
+ </template>
+ 
+     <script setup>
+         import './index.js'
+     </script>

+ 318 - 0
src/view/vtk/index.js

@@ -0,0 +1,318 @@
+import '@kitware/vtk.js/favicon';
+
+// Load the rendering pieces we want to use (for both WebGL and WebGPU)
+import '@kitware/vtk.js/Rendering/Profiles/Geometry';
+import '@kitware/vtk.js/Rendering/Profiles/Glyph';
+
+import DeepEqual from 'deep-equal';
+import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor';
+import vtkCubeSource from '@kitware/vtk.js/Filters/Sources/CubeSource';
+import vtkFullScreenRenderWindow from '@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow';
+import vtkMapper from '@kitware/vtk.js/Rendering/Core/Mapper';
+import vtkLineWidget from '@kitware/vtk.js/Widgets/Widgets3D/LineWidget';
+import vtkWidgetManager from '@kitware/vtk.js/Widgets/Core/WidgetManager';
+import vtkInteractorObserver from '@kitware/vtk.js/Rendering/Core/InteractorObserver';
+
+import { bindSVGRepresentation } from '/Examples/Widgets/Utilities/SVGHelpers';
+ import controlPanel from './controlPanel.vue';
+
+const { computeWorldToDisplay } = vtkInteractorObserver;
+
+// ----------------------------------------------------------------------------
+// Standard rendering code setup
+// ----------------------------------------------------------------------------
+
+const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({
+  background: [0, 0, 0],
+});
+const renderer = fullScreenRenderer.getRenderer();
+const renderWindow = fullScreenRenderer.getRenderWindow();
+
+const cube = vtkCubeSource.newInstance();
+const mapper = vtkMapper.newInstance();
+const actor = vtkActor.newInstance();
+
+actor.setMapper(mapper);
+mapper.setInputConnection(cube.getOutputPort());
+actor.getProperty().setOpacity(0.5);
+
+renderer.addActor(actor);
+
+// ----------------------------------------------------------------------------
+// Widget manager
+// ----------------------------------------------------------------------------
+
+const widgetManager = vtkWidgetManager.newInstance();
+widgetManager.setRenderer(renderer);
+
+let widget = null;
+
+let lineWidget = null;
+let selectedWidgetIndex = null;
+
+let getHandle = {};
+
+renderer.resetCamera();
+
+// -----------------------------------------------------------
+// UI control handling
+// -----------------------------------------------------------
+
+fullScreenRenderer.addController(controlPanel);
+
+// -----------------------------------------------------------
+// SVG handling
+// -----------------------------------------------------------
+
+const svgCleanupCallbacks = [];
+
+function setupSVG(w) {
+  svgCleanupCallbacks.push(
+    bindSVGRepresentation(renderer, w.getWidgetState(), {
+      mapState(widgetState, { size }) {
+        const textState = widgetState.getText();
+        const text = textState.getText();
+        const origin = textState.getOrigin();
+        if (origin) {
+          const coords = computeWorldToDisplay(renderer, ...origin);
+          const position = [coords[0], size[1] - coords[1]];
+          return {
+            text,
+            position,
+          };
+        }
+        return null;
+      },
+      render(data, h) {
+        if (data) {
+          return h(
+            'text',
+            {
+              key: 'lineText',
+              attrs: {
+                x: data.position[0],
+                y: data.position[1],
+                dx: 12,
+                dy: -12,
+                fill: 'white',
+                'font-size': 32,
+              },
+            },
+            data.text
+          );
+        }
+        return [];
+      },
+    })
+  );
+}
+
+// Text Modifiers ------------------------------------------
+
+function updateLinePos() {
+  const input = document.getElementById('linePos').value;
+  const subState = lineWidget.getWidgetState().getPositionOnLine();
+  subState.setPosOnLine(input / 100);
+  renderWindow.render();
+}
+
+function updateText() {
+  const input = document.getElementById('txtIpt').value;
+  if (lineWidget) {
+    lineWidget.setText(input);
+    renderWindow.render();
+  }
+}
+document.querySelector('#txtIpt').addEventListener('keyup', updateText);
+// updateText();
+
+function observeDistance() {
+  lineWidget.onInteractionEvent(() => {
+    document.getElementById('distance').innerHTML = widget
+      .getDistance()
+      .toFixed(2);
+  });
+
+  lineWidget.onEndInteractionEvent(() => {
+    document.getElementById('distance').innerHTML = widget
+      .getDistance()
+      .toFixed(2);
+  });
+}
+
+// setDistance();
+document.querySelector('#linePos').addEventListener('input', updateLinePos);
+// updateLinePos();
+
+// Handle Sources ------------------------------------------
+
+function updateCheckBoxes(handleId, shape) {
+  if (shape === 'voidSphere') {
+    document
+      .getElementById(`visiH${handleId}`)
+      .setAttribute('disabled', 'disabled');
+  } else if (
+    shape !== 'voidSphere' &&
+    document.getElementById(`visiH${handleId}`).getAttribute('disabled') ===
+      'disabled'
+  ) {
+    document.getElementById(`visiH${handleId}`).removeAttribute('disabled');
+  }
+}
+
+function updateHandleShape(handleId) {
+  const e = document.getElementById(`idh${handleId}`);
+  const shape = e.options[e.selectedIndex].value;
+  const handle = getHandle[handleId];
+  if (handle) {
+    handle.setShape(shape);
+    lineWidget.updateHandleVisibility(handleId - 1);
+    lineWidget.getInteractor().render();
+    updateCheckBoxes(handleId, shape);
+    observeDistance();
+  }
+}
+
+function setWidgetColor(currentWidget, color) {
+  currentWidget.getWidgetState().getHandle1().setColor(color);
+  currentWidget.getWidgetState().getHandle2().setColor(color);
+
+  currentWidget.setUseActiveColor(false);
+  currentWidget.getWidgetState().getMoveHandle().setColor(0.3);
+}
+
+// Restore color
+function unselectWidget(index) {
+  if (index != null) {
+    const widgetToUnselect = widgetManager.getWidgets()[selectedWidgetIndex];
+    setWidgetColor(widgetToUnselect, 0.5); // green
+  }
+  if (index === selectedWidgetIndex) {
+    selectedWidgetIndex = null;
+  }
+}
+
+function selectWidget(index) {
+  unselectWidget(selectedWidgetIndex);
+  if (index != null) {
+    const widgetToSelect = widgetManager.getWidgets()[index];
+    setWidgetColor(widgetToSelect, 0.2); // yellow
+  }
+  selectedWidgetIndex = index;
+}
+
+const inputHandle1 = document.getElementById('idh1');
+const inputHandle2 = document.getElementById('idh2');
+
+inputHandle1.addEventListener('input', updateHandleShape.bind(null, 1));
+inputHandle2.addEventListener('input', updateHandleShape.bind(null, 2));
+// inputHandle1.value =
+//   getHandle[1].getShape() === '' ? 'sphere' : getHandle[1].getShape();
+// inputHandle2.value =
+//   getHandle[2].getShape() === '' ? 'sphere' : getHandle[2].getShape();
+// updateCheckBoxes(1, getHandles[1].getShape());
+// updateCheckBoxes(2, getHandles[2].getShape());
+
+// document.getElementById(
+//   'visiH1'
+// ).checked = lineWidget.getWidgetState().getHandle1().getVisible();
+// document.getElementById(
+//   'visiH2'
+// ).checked = lineWidget.getWidgetState().getHandle2().getVisible();
+
+const checkBoxes = ['visiH1', 'visiH2'].map((id) =>
+  document.getElementById(id)
+);
+
+const handleCheckBoxInput = (e) => {
+  if (lineWidget == null) {
+    return;
+  }
+  if (e.target.id === 'visiH1') {
+    lineWidget.getWidgetState().getHandle1().setVisible(e.target.checked);
+    lineWidget.updateHandleVisibility(0);
+  } else {
+    lineWidget.getWidgetState().getHandle2().setVisible(e.target.checked);
+    lineWidget.updateHandleVisibility(1);
+  }
+  lineWidget.getInteractor().render();
+  renderWindow.render();
+};
+checkBoxes.forEach((checkBox) =>
+  checkBox.addEventListener('input', handleCheckBoxInput)
+);
+
+document.querySelector('#addWidget').addEventListener('click', () => {
+  let currentHandle = null;
+  widgetManager.releaseFocus(widget);
+  widget = vtkLineWidget.newInstance();
+  // widget.placeWidget(cube.getOutputData().getBounds());
+  currentHandle = widgetManager.addWidget(widget);
+  lineWidget = currentHandle;
+
+  selectWidget(widgetManager.getWidgets().length - 1);
+  setupSVG(widget);
+
+  getHandle = {
+    1: lineWidget.getWidgetState().getHandle1(),
+    2: lineWidget.getWidgetState().getHandle2(),
+  };
+
+  updateHandleShape(1);
+  updateHandleShape(2);
+
+  observeDistance();
+
+  widgetManager.grabFocus(widget);
+
+  currentHandle.onStartInteractionEvent(() => {
+    const index = widgetManager.getWidgets().findIndex((cwidget) => {
+      if (DeepEqual(currentHandle.getWidgetState(), cwidget.getWidgetState()))
+        return 1;
+      return 0;
+    });
+    getHandle = {
+      1: currentHandle.getWidgetState().getHandle1(),
+      2: currentHandle.getWidgetState().getHandle2(),
+    };
+    selectWidget(index);
+    lineWidget = currentHandle;
+    document.getElementById('idh1').value =
+      getHandle[1].getShape() === '' ? 'sphere' : getHandle[1].getShape();
+    document.getElementById('idh2').value =
+      getHandle[1].getShape() === '' ? 'sphere' : getHandle[2].getShape();
+    document.getElementById('visiH1').checked = lineWidget
+      .getWidgetState()
+      .getHandle1()
+      .getVisible();
+    document.getElementById('visiH2').checked = lineWidget
+      .getWidgetState()
+      .getHandle2()
+      .getVisible();
+    document.getElementById('txtIpt').value = lineWidget
+      .getWidgetState()
+      .getText()
+      .getText();
+  });
+});
+
+document.querySelector('#removeWidget').addEventListener('click', () => {
+  unselectWidget(selectedWidgetIndex);
+  widgetManager.removeWidget(widgetManager.getWidgets()[selectedWidgetIndex]);
+  if (svgCleanupCallbacks.length) svgCleanupCallbacks.pop()();
+  if (widgetManager.getWidgets().length !== 0) {
+    selectWidget(widgetManager.getWidgets().length - 1);
+    setWidgetColor(widgetManager.getWidgets()[selectedWidgetIndex], 0.2);
+  }
+});
+
+// -----------------------------------------------------------
+// globals
+// -----------------------------------------------------------
+
+global.widget = widget;
+global.renderer = renderer;
+global.fullScreenRenderer = fullScreenRenderer;
+global.renderWindow = renderWindow;
+global.widgetManager = widgetManager;
+global.line = lineWidget;

+ 241 - 0
src/view/vtk/vtk.vue

@@ -0,0 +1,241 @@
+<template>
+   <div>
+  <div :v-html="vtkhtml" ref="controlPanel1" id="fullscreen">
+   
+</div>
+</div>
+</template>
+    
+    <script setup>
+import '@kitware/vtk.js/favicon';
+
+// Load the rendering pieces we want to use (for both WebGL and WebGPU)
+import '@kitware/vtk.js/Rendering/Profiles/Geometry';
+import '@kitware/vtk.js/Rendering/Profiles/Glyph';
+
+import DeepEqual from 'deep-equal';
+import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor';
+import vtkCubeSource from '@kitware/vtk.js/Filters/Sources/CubeSource';
+import vtkFullScreenRenderWindow from '@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow';
+import vtkMapper from '@kitware/vtk.js/Rendering/Core/Mapper';
+import vtkImageData from '@kitware/vtk.js/Common/DataModel/ImageData';
+import vtkLabelWidget from '@kitware/vtk.js/Widgets/Widgets3D/LabelWidget';
+import vtkWidgetManager from '@kitware/vtk.js/Widgets/Core/WidgetManager';
+import vtkInteractorObserver from '@kitware/vtk.js/Rendering/Core/InteractorObserver';
+import vtkTexture from '@kitware/vtk.js/Rendering/Core/Texture';
+import { bindSVGRepresentation } from '/Examples/Widgets/Utilities/SVGHelpers';
+import vtkVolume from 'vtk.js/Sources/Rendering/Core/Volume';
+const { computeWorldToDisplay } = vtkInteractorObserver
+import t4 from "@/assets/img/t4.png";
+let vtkhtml=ref(` 
+<div>
+  <button id="addWidget">Add widget</button> 
+  <br />
+  <button id="removeWidget">Remove widget</button> 
+  <br />
+  <br />
+  <div>Distance: <span id="distance">0</span></div>
+  <br />
+  <div>Text:</div>
+  <textarea id="txtIpt" name="name"></textarea>
+  <br />
+  <br />
+  <div>Line position</div>
+  <input
+    title="Line position"
+    id="linePos"
+    type="range"
+    min="0"
+    max="100"
+    step="1"
+    value="50"
+  />
+  <br />
+
+  <br />
+  <label for="pet-select">Handle1</label>
+  <br />
+
+  <select name="handle1" class="HandleSource" id="idh1">
+    <option value="sphere">Sphere</option>
+    <option value="cone">Cone</option>
+    <option value="cube">Cube</option>
+    <option value="triangle">Triangle</option>
+    <option value="4pointsArrowHead">4 points arrow head</option>
+    <option value="6pointsArrowHead">6 points arrow head</option>
+    <option value="star">Star</option>
+    <option value="disk">Disk</option>
+    <option value="circle">Circle</option>
+    <option value="viewFinder">View Finder</option>
+    <option value="voidSphere">None</option>
+  </select>
+  <div>Visibility
+    <input id="visiH1" type="checkbox" />
+    <br />
+  </div>
+  <br />
+  <label for="pet-select">Handle2</label>
+  <br />
+  <select name="handle2" class="HandleSource" id="idh2">
+    <option value="sphere">Sphere</option>
+    <option value="cone">Cone</option>
+    <option value="cube">Cube</option>
+    <option value="triangle">Triangle</option>
+    <option value="4pointsArrowHead">4 points arrow head</option>
+    <option value="6pointsArrowHead">6 points arrow head</option>
+    <option value="star">Star</option>
+    <option value="disk">Disk</option>
+    <option value="circle">Circle</option>
+    <option value="viewFinder">View Finder</option>
+    <option value="voidSphere">None</option>
+  </select>
+  <div>Visibility
+    <input id="visiH2" type="checkbox" />
+    <br />
+  </div>
+</div>`)
+const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({
+  background: [0, 0, 0],
+});
+const renderer = fullScreenRenderer.getRenderer();
+const renderWindow = fullScreenRenderer.getRenderWindow();
+
+const cube = vtkCubeSource.newInstance();//立方体
+const mapper = vtkMapper.newInstance();//映射
+const actor = vtkActor.newInstance();// 渲染场景实体
+
+actor.setMapper(mapper);
+mapper.setInputConnection(cube.getOutputPort());
+actor.getProperty().setOpacity(0.5);
+
+renderer.addActor(actor);
+
+// ----------------------------------------------------------------------------
+// Widget manager
+// ----------------------------------------------------------------------------
+
+const widgetManager = vtkWidgetManager.newInstance();
+widgetManager.setRenderer(renderer);
+
+let widget = null;
+
+let lineWidget = null;
+let selectedWidgetIndex = null;
+
+let getHandle = {};
+
+renderer.resetCamera();
+//添加图片
+const texture = vtkTexture.newInstance();
+    texture.setInterpolate(true);
+ const volume = vtkVolume.newInstance();
+  volume.setMapper(mapper);
+const image = new Image();
+image.src = '/src/assets/img/t4.png';
+console.log(image);
+image.onload = function() {
+  texture.setInputData(image);
+ volume.setProperty({ texture: texture });
+  // texture.setInputData(image); 
+  // actor.setMapper(mapper);
+  // console.log(actor);
+  // actor.getProperty().setTexture(texture);   
+  // renderWindow.render();
+};
+// ----------------------------------------------------------------------------
+// SVG
+// ----------------------------------------------------------------------------
+onMounted(() => {
+  var full = vtkhtml.value;
+ fullScreenRenderer.addController(full);
+ const svgCleanupCallbacks = [];
+
+function setupSVG(w) {
+  svgCleanupCallbacks.push(
+    bindSVGRepresentation(renderer, w.getWidgetState(), {
+      mapState(widgetState, { size }) {
+        const textState = widgetState.getText();
+        const text = textState.getText();
+        const origin = textState.getOrigin();
+        if (origin) {
+          const coords = computeWorldToDisplay(renderer, ...origin);
+          const position = [coords[0], size[1] - coords[1]];
+          return {
+            text,
+            position,
+          };
+        }
+        return null;
+      },
+      render(data, h) {
+        if (data) {
+          console.log(data);
+      //  data.text='2人'
+          console.log(data.text+""+'12124')
+          return h(
+            'text',
+            {
+              key: 'lineText',
+              attrs: {
+                x: data.position[0],
+                y: data.position[1],
+                dx: 12,
+                dy: -12,
+                fill: 'red',
+                'font-size': 16,
+              },
+            },
+            data.text
+           
+          );
+        }
+        return [];
+      },
+    })
+  );
+}
+ // Update text
+ function updateText() {
+   const input = document.getElementById('txtIpt').value;
+   console.log(input);
+   if (currentHandle) {
+     currentHandle.setText(input);
+     renderWindow.render();
+   }
+ }
+
+ let currentHandle = null;
+const handleTextProps = new Map();
+//const svgCleanupCallbacks = new Map();
+document.querySelector('#txtIpt').addEventListener('keyup', updateText);
+document.querySelector('#addWidget').addEventListener('click', () => {
+   const widget = vtkLabelWidget.newInstance();
+   const handle = widgetManager.addWidget(widget);
+
+   const textProps = {
+     fontSize: 32,
+     fontColor: 'white',
+   };
+   handleTextProps.set(handle, textProps);
+   
+   handleTextProps.set(handle, setupSVG(handle));
+   handle.onStartInteractionEvent(() => {
+     currentHandle = handle;
+   });
+   widgetManager.grabFocus(widget);
+ });
+
+
+// -----------------------------------------------------------
+// globals
+// -----------------------------------------------------------
+
+// global.widget = widget;
+// global.renderer = renderer;
+// global.fullScreenRenderer = fullScreenRenderer;
+// global.renderWindow = renderWindow;
+// global.widgetManager = widgetManager;
+// global.line = lineWidget;
+
+});
+    </script>

+ 247 - 0
src/view/vtk/vtk2.vue

@@ -0,0 +1,247 @@
+<template>
+    <div>
+   <div :v-html="vtkhtml" ref="controlPanel1" id="fullscreen">
+ </div>
+ </div>
+     
+ </template>
+     
+     <script setup>
+ import '@kitware/vtk.js/favicon';
+ import { ref, onMounted, reactive } from "vue";
+ // Load the rendering pieces we want to use (for both WebGL and WebGPU)
+ import '@kitware/vtk.js/Rendering/Profiles/Geometry';
+ import '@kitware/vtk.js/Rendering/Profiles/Glyph';
+ import vtkFullScreenRenderWindow from '@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow';
+ import vtkInteractorStyleImage from '@kitware/vtk.js/Interaction/Style/InteractorStyleImage';
+ 
+ import vtkWidgetManager from '@kitware/vtk.js/Widgets/Core/WidgetManager';
+ import vtkLabelWidget from '@kitware/vtk.js/Widgets/Widgets3D/LabelWidget';
+ 
+ import vtkInteractorObserver from '@kitware/vtk.js/Rendering/Core/InteractorObserver';
+ import {
+   bindSVGRepresentation,
+   multiLineTextCalculator,
+   VerticalTextAlignment,
+   makeListenableSVGNode,
+ } from '/Examples/Widgets/Utilities/SVGHelpers';
+ import s3 from "@/assets/img/s3.png";
+ let vtkhtml=ref(` 
+     <div>
+   <button id="addLabel">Addlabel</button>
+   <button id="deleteLabel">Deletelabel</button>
+   <div>Text:</div>
+   <textarea id="txtIpt" name="name"></textarea>
+   <div>Font size</div>
+   <input
+     title="Font size"
+     id="fontSize"
+     type="range"
+     min="8"
+     max="64"
+     step="1"
+     value="16"
+   />
+   <div>Color</div>
+   <select name="color" class="str" id="color">
+     <option value="white">White</option>
+     <option value="black">Black</option>
+     <option value="red">Red</option>
+     <option value="green">Green</option>
+     <option value="blue">Blue</option>
+   </select>
+ </div>`)
+ const { computeWorldToDisplay } = vtkInteractorObserver;
+ 
+ // ----------------------------------------------------------------------------
+ // Standard rendering code setup
+ // ----------------------------------------------------------------------------
+ 
+ const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance();
+ const renderer = fullScreenRenderer.getRenderer();
+ const renderWindow = fullScreenRenderer.getRenderWindow();
+ const iStyle = vtkInteractorStyleImage.newInstance();
+ renderWindow.getInteractor().setInteractorStyle(iStyle);
+ 
+ const widgetManager = vtkWidgetManager.newInstance();
+ widgetManager.setRenderer(renderer);
+ 
+ renderer.resetCamera();
+ widgetManager.enablePicking();
+ 
+ // ----------------------------------------------------------------------------
+ // SVG
+ // ----------------------------------------------------------------------------
+ onMounted(() => {
+   var full = vtkhtml.value;
+  fullScreenRenderer.addController(full);
+ 
+ const handleTextProps = new Map();
+ 
+ function setupSVG(viewWidget) {
+   bindSVGRepresentation(renderer, viewWidget.getWidgetState(), {
+     mapState(widgetState, { size }) {
+       const textState = widgetState.getText();
+       const text = textState.getText();
+       const origin = textState.getOrigin();
+       if (origin && textState.getVisible()) {
+         const coords = computeWorldToDisplay(renderer, ...origin);
+         const position = [coords[0], size[1] - coords[1]];
+         return {
+           text,
+           position,
+           active: textState.getActive(),
+         };
+       }
+       return null;
+     },
+     render(data, h) {
+       if (data) {
+         const nodes = [];
+         const { text, position, active } = data;
+         console.log(data);
+         const { fontColor, fontSize } = handleTextProps.get(viewWidget);
+ 
+         if (text.trim().length === 0) {
+           nodes.push(
+             h('circle', {
+               key: 'circle',
+               attrs: {
+                 r: 5,
+                 stroke: 'red',
+                 fill: 'red',
+                 cx: position[0],
+                 cy: position[1],
+               },
+             })
+           );
+         }
+         const lines = text.split('\n'+'2个人');
+         const dys = multiLineTextCalculator(
+           lines.length,
+           fontSize,
+           VerticalTextAlignment.MIDDLE
+         );
+         console.log(lines);
+         nodes.push(
+           ...lines.map((line, index) =>
+             makeListenableSVGNode(
+               h(
+                 'text',
+                 {
+                   key: index,
+                   attrs: {
+                     x: position[0],
+                     y: position[1],
+                     dx: 12,
+                     dy: dys[index],
+                     fill: fontColor,
+                     'font-size': fontSize,
+                     'text-anchor': 'middle',
+                     'font-weight': active ? 'bold' : 'normal',
+                   },
+                   style: {
+                     cursor: 'pointer',
+                   },
+                   on: {
+                     pointerenter() {
+                       widgetManager.disablePicking();
+                       viewWidget.activateHandle({
+                         selectedState: viewWidget.getWidgetState().getText(),
+                       });
+                     },
+                     pointerleave: () => {
+                       viewWidget.deactivateAllHandles();
+                       widgetManager.enablePicking();
+                     },
+                   },
+                 },
+                 line
+               )
+             )
+           )
+         );
+ 
+         return nodes;
+       }
+       return [];
+     },
+   });
+ }
+ 
+ // -----------------------------------------------------------
+ // UI control handling
+ // -----------------------------------------------------------
+ let currentHandle = null;
+ const svgCleanupCallbacks = new Map();
+ // Add a new label
+ document.querySelector('#addLabel').addEventListener('click', () => {
+   const widget = vtkLabelWidget.newInstance();
+   const handle = widgetManager.addWidget(widget);
+   widgetManager.grabFocus(widget);
+ 
+   const textProps = {
+     fontSize: 32,
+     fontColor: 'white',
+   };
+   handleTextProps.set(handle, textProps);
+   
+    svgCleanupCallbacks.set(handle, setupSVG(handle));
+   // Update control panel when a label is selected
+   handle.onStartInteractionEvent(() => {
+     currentHandle = handle;
+     console.log(handle)
+    // document.getElementById('txtIpt').value = currentHandle.getText() || '';
+    //  document.getElementById('fontSize').value = textProps.fontSize;
+    //  document.getElementById('color').value = textProps.fontColor;
+   });
+ });
+ 
+ // Delete a label
+ document.querySelector('#deleteLabel').addEventListener('click', () => {
+   if (currentHandle) {
+     currentHandle.reset();
+     widgetManager.removeWidget(currentHandle);
+     svgCleanupCallbacks.get(currentHandle)();
+     svgCleanupCallbacks.delete(currentHandle);
+     handleTextProps.delete(currentHandle);
+     currentHandle = null;
+   }
+ });
+ 
+ // Update text
+ function updateText() {
+   const input = document.getElementById('txtIpt').value;
+   if (currentHandle) {
+     currentHandle.setText(input);
+     renderWindow.render();
+   }
+ }
+ document.querySelector('#txtIpt').addEventListener('keyup', updateText);
+ 
+ // Update font size
+ function updateFontSize() {
+   const input = document.getElementById('fontSize').value;
+   if (currentHandle) {
+     handleTextProps.set(currentHandle, {
+       ...handleTextProps.get(currentHandle),
+       fontSize: input,
+     });
+     currentHandle.getWidgetState().modified(); // render svg
+   }
+ }
+ document.querySelector('#fontSize').addEventListener('input', updateFontSize);
+ // Update color
+ function updateColor() {
+   const input = document.getElementById('color').value;
+   if (currentHandle) {
+     handleTextProps.set(currentHandle, {
+       ...handleTextProps.get(currentHandle),
+       fontColor: input,
+     });
+     currentHandle.getWidgetState().modified(); // render svg
+   }
+ }
+ document.querySelector('#color').addEventListener('input', updateColor);
+ });
+     </script>

+ 405 - 404
src/view/vtkContainer.vue

@@ -1,413 +1,414 @@
 <template>
-<div class="vtk">
-    <!-- <div id="vtkContainer" /> -->
-
-  </div>
-
-</template>
-
-<script setup>
-
-import * as d3 from "d3-scale";
-import { formatDefaultLocale } from "d3-format";
-import { ref, onMounted, reactive } from "vue";
-import "@kitware/vtk.js/Rendering/Profiles/Geometry";
-import vtkRenderWindowWithControlBar from "@kitware/vtk.js/Rendering/Misc/RenderWindowWithControlBar";
-import vtkFullScreenRenderWindow from "@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow";
-
-import vtkActor from "@kitware/vtk.js/Rendering/Core/Actor";
-import vtkMapper from "@kitware/vtk.js/Rendering/Core/Mapper";
-import vtkUnstructuredDataReader from "../reader/UnstructuredDataReader.js";
-import { createFireControl } from "../control/fireControl.js";
-import vtkScalarBarActor from "@kitware/vtk.js/Rendering/Core/ScalarBarActor";
-import vtkLookupTable from "@kitware/vtk.js/Common/Core/LookupTable";
-import vtkDataArray from "@kitware/vtk.js/Common/Core/DataArray.js";
-import vtkColorTransferFunction from "@kitware/vtk.js/Rendering/Core/ColorTransferFunction";
-import { I } from "@kitware/vtk.js/macros2.js";
-import { Representation } from "@kitware/vtk.js/Rendering/Core/Property/Constants";
-import evolutionView from "./evolutionView.vue";
-
-import vtkConeSource from "@kitware/vtk.js/Filters/Sources/ConeSource";
-import vtkSphereMapper from "@kitware/vtk.js/Rendering/Core/SphereMapper";
-import vtkPixelSpaceCallbackMapper from "@kitware/vtk.js/Rendering/Core/PixelSpaceCallbackMapper";
-import vtkSphereSource from "@kitware/vtk.js/Filters/Sources/SphereSource";
-
-import vtkAxesActor from "@kitware/vtk.js/Rendering/Core/AxesActor";
-import vtkCubeAxesActor from "@kitware/vtk.js/Rendering/Core/CubeAxesActor";
-import vtk2DShape from '@kitware/vtk.js/Filters/Sources/Arrow2DSource';
-import vtkTriangleFilter from '@kitware/vtk.js/Filters/General/TriangleFilter';
-// const props = {};
-let time = 3 * 60;
-const props= defineProps({
-  vatkval:{
-        type: Object,
-    },
-    arrvalue:{
-      type: Array,
-     
+  <div class="vtk">
+      <!-- <div id="vtkContainer" /> -->
+  
+    </div>
+  
+  </template>
+  
+  <script setup>
+  
+  import * as d3 from "d3-scale";
+  import { formatDefaultLocale } from "d3-format";
+  import { ref, onMounted, reactive } from "vue";
+  import "@kitware/vtk.js/Rendering/Profiles/Geometry";
+  import vtkRenderWindowWithControlBar from "@kitware/vtk.js/Rendering/Misc/RenderWindowWithControlBar";
+  import vtkFullScreenRenderWindow from "@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow";
+  
+  import vtkActor from "@kitware/vtk.js/Rendering/Core/Actor";
+  import vtkMapper from "@kitware/vtk.js/Rendering/Core/Mapper";
+  import vtkUnstructuredDataReader from "../reader/UnstructuredDataReader.js";
+  import { createFireControl } from "../control/fireControl.js";
+  import vtkScalarBarActor from "@kitware/vtk.js/Rendering/Core/ScalarBarActor";
+  import vtkLookupTable from "@kitware/vtk.js/Common/Core/LookupTable";
+  import vtkDataArray from "@kitware/vtk.js/Common/Core/DataArray.js";
+  import vtkColorTransferFunction from "@kitware/vtk.js/Rendering/Core/ColorTransferFunction";
+  import { I } from "@kitware/vtk.js/macros2.js";
+  import { Representation } from "@kitware/vtk.js/Rendering/Core/Property/Constants";
+  import evolutionView from "./evolutionView.vue";
+  
+  import vtkConeSource from "@kitware/vtk.js/Filters/Sources/ConeSource";
+  import vtkSphereMapper from "@kitware/vtk.js/Rendering/Core/SphereMapper";
+  import vtkPixelSpaceCallbackMapper from "@kitware/vtk.js/Rendering/Core/PixelSpaceCallbackMapper";
+  import vtkSphereSource from "@kitware/vtk.js/Filters/Sources/SphereSource";
+  
+  import vtkAxesActor from "@kitware/vtk.js/Rendering/Core/AxesActor";
+  import vtkCubeAxesActor from "@kitware/vtk.js/Rendering/Core/CubeAxesActor";
+  import vtk2DShape from '@kitware/vtk.js/Filters/Sources/Arrow2DSource';
+  import vtkTriangleFilter from '@kitware/vtk.js/Filters/General/TriangleFilter';
+  // const props = {};
+  let time = 3 * 60;
+  const props= defineProps({
+    vatkval:{
+          type: Object,
+      },
+      arrvalue:{
+        type: Array,
+       
+      }
+   });
+  // let title1=ref("我是父组件")
+  let dialogVisible = ref(false);
+  // let num = ref(4);
+  // let starttime = ref(1);
+  // let endtime = ref(60);
+  // let timenum = ref(2);
+  // let isstop = ref(false);
+   let arrvalue = reactive([]);
+  
+  // 响应式状态
+  const count = ref(0);
+  const opacity = ref(0.1);
+  const min = ref(0);
+  const max = ref(1);
+  const scalarFAll = ref([]); //火灾标量
+  const scalarWAll = ref([]); //水灾标量
+  /*
+  Temperature:温度
+  Pressure:压强
+  SO2:SO2
+  CO2:CO2
+  Height:水位高度
+  */
+  // const scalarName = ref("CO2");
+  //  const filedir =ref("data/Fire/");
+  //const scalarName = ref("Height");
+  const filedir = ref("data/Water/");
+  // const renderWindowWith = vtkRenderWindowWithControlBar.newInstance({
+  //     controlSize: 11,
+  //   });
+  
+  const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance();
+  const renderer = fullScreenRenderer.getRenderer();
+  const renderWindow = fullScreenRenderer.getRenderWindow();
+  const mapper = vtkMapper.newInstance();
+  const actor = vtkActor.newInstance();
+  
+  // actor.getProperty().setRepresentation(Representation.WIREFRAME);//线
+  // actor.getProperty().setRepresentation(Representation.POINTS);//点
+  actor.getProperty().setRepresentation(Representation.SURFACE); //面
+  
+  // 用来修改状态、触发更新的函数
+  function inOpacity() {
+    opacity.value = opacity.value + 0.1;
+    actor.getProperty().setOpacity(opacity.value);
+    renderWindow.render();
+  }
+  function getMinMax(scalars) {
+    // console.log("getMinMax:",scalars);
+    min.value = scalars[0];
+    max.value = scalars[0];
+    for (let index = 0; index <= scalars.length; index++) {
+      let scalar = scalars[index];
+      if (min.value > scalar) {
+        min.value = scalar;
+      }
+      if (max.value < scalar) {
+        max.value = scalar;
+      }
     }
- });
-// let title1=ref("我是父组件")
-let dialogVisible = ref(false);
-// let num = ref(4);
-// let starttime = ref(1);
-// let endtime = ref(60);
-// let timenum = ref(2);
-// let isstop = ref(false);
- let arrvalue = reactive([]);
-
-// 响应式状态
-const count = ref(0);
-const opacity = ref(0.1);
-const min = ref(0);
-const max = ref(1);
-const scalarFAll = ref([]); //火灾标量
-const scalarWAll = ref([]); //水灾标量
-/*
-Temperature:温度
-Pressure:压强
-SO2:SO2
-CO2:CO2
-Height:水位高度
-*/
-// const scalarName = ref("CO2");
-//  const filedir =ref("data/Fire/");
-//const scalarName = ref("Height");
-const filedir = ref("data/Water/");
-// const renderWindowWith = vtkRenderWindowWithControlBar.newInstance({
-//     controlSize: 11,
-//   });
-
-const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance();
-const renderer = fullScreenRenderer.getRenderer();
-const renderWindow = fullScreenRenderer.getRenderWindow();
-const mapper = vtkMapper.newInstance();
-const actor = vtkActor.newInstance();
-
-// actor.getProperty().setRepresentation(Representation.WIREFRAME);//线
-// actor.getProperty().setRepresentation(Representation.POINTS);//点
-actor.getProperty().setRepresentation(Representation.SURFACE); //面
-
-// 用来修改状态、触发更新的函数
-function inOpacity() {
-  opacity.value = opacity.value + 0.1;
-  actor.getProperty().setOpacity(opacity.value);
-  renderWindow.render();
-}
-function getMinMax(scalars) {
-  // console.log("getMinMax:",scalars);
-  min.value = scalars[0];
-  max.value = scalars[0];
-  for (let index = 0; index <= scalars.length; index++) {
-    let scalar = scalars[index];
-    if (min.value > scalar) {
-      min.value = scalar;
+    // console.log("max,min:", max.value, min.value);
+  }
+  //时间
+  function sleep(numberMillis) {
+    var now = new Date();
+    var exitTime = now.getTime() + numberMillis;
+    console.log(exitTime);
+  }
+  
+  
+  
+  
+  
+  // 用来修改状态、触发更新的函数
+  function increment() {
+    isstop.value = false;
+    if (count.value == endtime.value) {
+      return;
     }
-    if (max.value < scalar) {
-      max.value = scalar;
+    count.value++;
+    changeScalar();
+  }
+  function changeScalar() {
+    console.log(props.arrvalue)
+    var scalars;
+    if (props.arrvalue[0] == "fire") {
+      scalars = scalarFAll.value[count.value];
+    } else {
+      scalars = scalarWAll.value[count.value];
     }
+    const polydata = mapper.getInputData();
+    const scalarArray = scalars.get(props.arrvalue[1]);
+    // console.log("scalarArray:", scalarArray);
+    const dataArray = vtkDataArray.newInstance({
+      name: props.arrvalue[1],
+      size: polydata.getNumberOfPoints(),
+    });
+    dataArray.setData(scalarArray);
+    getMinMax(scalarArray);
+    mapper.setScalarRange(min.value, max.value); //设置范围
+    scalarBarActor.setAxisLabel(props.arrvalue[1]);
+    polydata.getPointData().setScalars(dataArray);
+    mapper.clearColorArrays(); //强制重建颜色
+    actor.getProperty().setOpacity(count.value); //设置错误的透明度使得页面重新加载  不设置不刷新页面
+    renderWindow.render();
   }
-  // console.log("max,min:", max.value, min.value);
-}
-//时间
-function sleep(numberMillis) {
-  var now = new Date();
-  var exitTime = now.getTime() + numberMillis;
-  console.log(exitTime);
-}
-
-
-
-
-
-// 用来修改状态、触发更新的函数
-function increment() {
-  isstop.value = false;
-  if (count.value == endtime.value) {
-    return;
+  //加载所有 标量数据
+  function loadScalarAll() {
+    //水灾
+    // for (let index = 0; index <= 15; index++) {
+      //   const reader = vtkUnstructuredDataReader.newInstance();
+    //   const url="http://192.168.0.131:8187/TransServlet?channelNo=service&clientToken=e47b87eec69545559d1e81e56626da68&transCode=D00009&userId=5f06c8bc77234f969d13e160b54c27e3&aid=5&stype=Water&step="
+    //   reader.setUrl(url + index ).then(() => {
+    //     const scalars = reader.getOutputData(1);
+    //     scalarWAll.value[index] = scalars;
+    //   });
+    // }
+    //火灾
+    for (let index = 1; index <= 4; index++) {
+      const reader = vtkUnstructuredDataReader.newInstance();
+      const url =
+        "http://192.168.0.131:8187/TransServlet?channelNo=service&clientToken=e47b87eec69545559d1e81e56626da68&transCode=D00009&userId=5f06c8bc77234f969d13e160b54c27e3&aid=5&stype=Fire&step=";
+      reader.setUrl(url + index).then(() => {
+        console.log("url + index ", index);
+        const scalars = reader.getOutputData(1);
+        scalarFAll.value[index] = scalars;
+        console.log(scalars);
+        console.log(2222)
+        console.log("url end  ");
+      });
+    }
+    console.log("scalarAll.value:", scalarFAll);
   }
-  count.value++;
-  changeScalar();
-}
-function changeScalar() {
-  console.log(props.arrvalue)
-  var scalars;
-  if (props.arrvalue[0] == "fire") {
-    scalars = scalarFAll.value[count.value];
-  } else {
-    scalars = scalarWAll.value[count.value];
+  //设置
+  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);
+    };
   }
-  const polydata = mapper.getInputData();
-  const scalarArray = scalars.get(props.arrvalue[1]);
-  // console.log("scalarArray:", scalarArray);
-  const dataArray = vtkDataArray.newInstance({
-    name: props.arrvalue[1],
-    size: polydata.getNumberOfPoints(),
+  //安装时
+  onMounted(() => {
+    arrvalue = ["Water", "Height"];
+    // const sphereSource = vtkSphereSource.newInstance({
+    //   center: [495960.36, 5402540.18, -424.27],
+    //   radius: 3.02,
+    //   phiResolution: 20,
+    //   thetaResolution:20,
+    // });
+  
+    // const mapper1 = vtkMapper.newInstance();
+    // mapper1.setInputConnection(sphereSource.getOutputPort());
+    // const actor1 = vtkActor.newInstance();
+    // actor1.setMapper(mapper1);
+    // actor1.getProperty().setColor([0.95, 0.45, 0.95]);
+    // renderer.addActor(actor1);
+  
+  // choices include triangle, star, arrow4points, arrow6points
+    const initialValues = { base:-0.1,shape: 'arrow4points',center: [495960.36, 5402540.18, -424.27],width: 20.0,height:20,direction:[0,1,1] };
+     
+    // const triangleFilter = vtkTriangleFilter.newInstance();
+    const shapeSource2 = vtk2DShape.newInstance(initialValues);
+    // triangleFilter.setInputConnection(shapeSource2.getOutputPort());
+  
+    const mapper2 = vtkMapper.newInstance();
+    mapper2.setInputConnection(shapeSource2.getOutputPort());
+    const actor2 = vtkActor.newInstance();
+    actor2.setMapper(mapper2);
+    renderer.addActor(actor2);
+  
+    // const cubeAxes = vtkCubeAxesActor.newInstance();
+    // cubeAxes.setCamera(renderer.getActiveCamera());
+    // cubeAxes.setDataBounds(actor1.getBounds());
+    // renderer.addActor(cubeAxes);
+  
+  
+    // const axesActor = vtkAxesActor.newInstance();
+    // renderer.addActor(axesActor);
+  
+  
+  
+    renderer.resetCamera();
+    renderWindow.render();
+    fireRead();
   });
-  dataArray.setData(scalarArray);
-  getMinMax(scalarArray);
-  mapper.setScalarRange(min.value, max.value); //设置范围
-  scalarBarActor.setAxisLabel(props.arrvalue[1]);
-  polydata.getPointData().setScalars(dataArray);
-  mapper.clearColorArrays(); //强制重建颜色
-  actor.getProperty().setOpacity(count.value); //设置错误的透明度使得页面重新加载  不设置不刷新页面
-  renderWindow.render();
-}
-//加载所有 标量数据
-function loadScalarAll() {
-  //水灾
-  // for (let index = 0; index <= 15; index++) {
-    //   const reader = vtkUnstructuredDataReader.newInstance();
-  //   const url="http://192.168.0.131:8187/TransServlet?channelNo=service&clientToken=e47b87eec69545559d1e81e56626da68&transCode=D00009&userId=5f06c8bc77234f969d13e160b54c27e3&aid=5&stype=Water&step="
-  //   reader.setUrl(url + index ).then(() => {
-  //     const scalars = reader.getOutputData(1);
-  //     scalarWAll.value[index] = scalars;
-  //   });
-  // }
-  //火灾
-  for (let index = 1; index <= 4; index++) {
-    const reader = vtkUnstructuredDataReader.newInstance();
-    const url =
-      "http://192.168.0.131:8187/TransServlet?channelNo=service&clientToken=e47b87eec69545559d1e81e56626da68&transCode=D00009&userId=5f06c8bc77234f969d13e160b54c27e3&aid=5&stype=Fire&step=";
-    reader.setUrl(url + index).then(() => {
-      console.log("url + index ", index);
-      const scalars = reader.getOutputData(1);
-      scalarFAll.value[index] = scalars;
-      console.log(scalars);
-      console.log(2222)
-      console.log("url end  ");
-    });
+  
+  function fireRead() {
+    var fcon = createFireControl();
+    fcon
+      .initGemetry()
+      .then((result) => {
+        fcon
+          .initScalrs()
+          .then((result) => {
+           // console.log(fcon.scalars)
+            const scalarArray = fcon.scalars[3].get("Pressure");
+            //console.log("scalarArray:", scalarArray);
+            const dataArray = vtkDataArray.newInstance({ 
+              name: arrvalue[1],
+              size: fcon.polydata.getNumberOfPoints(),
+            });
+            console.log(dataArray)
+            dataArray.setData(scalarArray);
+            fcon.polydata.getPointData().setScalars(dataArray);
+            mapper.setInputData(fcon.polydata);
+            getMinMax(scalarArray);
+            mapper.setScalarRange(min.value, max.value); //设置范围
+            actor.setMapper(mapper);
+            renderer.addActor(actor);
+  
+            initScalarBar();
+            renderer.resetCamera();
+            renderWindow.render();
+          })
+          .catch((err) => {});
+      })
+      .catch((err) => {});
+  }
+  
+  // 初始化 bar
+  function initScalarBar() {
+    const scalarBarActor = vtkScalarBarActor.newInstance();
+    let lut = mapper.getLookupTable();
+    scalarBarActor.setScalarsToColors(lut);
+    // console.log("lut:", lut.getRange());
+    // Change the number of ticks (TODO: add numberOfTicks to ScalarBarActor)
+    scalarBarActor.setGenerateTicks(generateTicks(5));
+    scalarBarActor.setAxisLabel(arrvalue[1]);
+    scalarBarActor.setDrawAboveRangeSwatch(true);
+    //修改设条颜色
+    const ctf = vtkColorTransferFunction.newInstance();
+    ctf.addRGBPoint(0.0, 0.0, 0.0, 1.0);
+    ctf.addRGBPoint(1.0, 0.0, 1.0, 0.5);
+    ctf.addRGBPoint(2.0, 0.0, 1.0, 0.0);
+    ctf.addRGBPoint(3.0, 1.0, 0.5, 0.0);
+    ctf.addRGBPoint(4.0, 1.0, 0.0, 0.0);
+    mapper.setLookupTable(ctf);
+    lut = mapper.getLookupTable();
+    scalarBarActor.setScalarsToColors(lut);
+    renderer.addActor(scalarBarActor);
+  }
+  defineExpose({changeScalar})
+  </script>
+  
+  <style>
+  #vtkContainer{
+    position: relative;
+  }
+  .vtk{
+    position: relative;
+  }
+  .controls {
+    position: absolute;
+    top: 25px;
+    left: 25px;
+    background: white;
+    padding: 12px;
+  }
+  .haha {
+    color: #fff;
+  }
+  .tool {
+    position: fixed;
+    top: 50px;
+    left: 20px;
+  
+    z-index: 205;
+  }
+  .img {
+    width: 48px;
+    margin: -6px 0;
+    padding: 8px 10px;
+    background-color: rgba(255, 255, 255, 0.1);
+    font-size: 12px;
+    transform: scale(0.9);
+  }
+  .img span {
+    color: #fff;
+    display: inline-block;
+  }
+  .img .el-image {
+    width: 34px;
+  }
+  .leftdialong {
+    padding: 15px;
+    width: 300px;
+    position: relative;
+    top: -248px;
+    left: 69px;
+    border-radius: 5px;
+    box-shadow: 0px 3px 10px rgba(255, 255, 255, 0.1);
+  }
+  .leftdialong .el-form-item__label {
+    font-size: 12px;
+    color: #fff !important;
+    padding-left: 6px;
+  }
+  .time {
+    color: #fff;
+    font-size: 12px;
+    margin-bottom: 30px;
+  }
+  .itemlist {
+    display: flex;
+  }
+  .item {
+    background-color: rgba(255, 255, 255, 0.1);
+    margin: 5px;
+    padding: 5px 9px;
+    border-radius: 5px;
+    font-size: 14px;
+    transform: scale(0.8);
+    color: #fff;
+  }
+  .dialog-footer {
+    margin-top: 30px;
+    text-align: right;
+  }
+  .block {
+    display: flex;
+  }
+  .demonstration {
+    padding: 5px 5px 5px 0;
+    font-size: 12px;
+    color: #fff;
+    display: inline-block;
+    width: 100px;
+    height: 24px;
+    line-height: 24px;
+  }
+  .block .el-slider {
+    padding: 0 5px;
+  }
+  .cascadeer .el-cascader {
+    width: 100%;
+  }
+  .cascadeer .asterisk-left {
+    width: 100% !important;
+    font-size: 12px;
+  }
+  .btn {
+    background-color: rgba(255, 255, 255, 0.1);
+    margin: 5px;
+    padding: 5px 9px;
+    border-radius: 5px;
+    font-size: 14px;
+    transform: scale(0.8);
+    color: #fff;
   }
-  console.log("scalarAll.value:", scalarFAll);
-}
-//设置
-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);
-  };
-}
-//安装时
-onMounted(() => {
-  arrvalue = ["Water", "Height"];
-  // const sphereSource = vtkSphereSource.newInstance({
-  //   center: [495960.36, 5402540.18, -424.27],
-  //   radius: 3.02,
-  //   phiResolution: 20,
-  //   thetaResolution:20,
-  // });
-
-  // const mapper1 = vtkMapper.newInstance();
-  // mapper1.setInputConnection(sphereSource.getOutputPort());
-  // const actor1 = vtkActor.newInstance();
-  // actor1.setMapper(mapper1);
-  // actor1.getProperty().setColor([0.95, 0.45, 0.95]);
-  // renderer.addActor(actor1);
-
-// choices include triangle, star, arrow4points, arrow6points
-  const initialValues = { base:-0.1,shape: 'arrow4points',center: [495960.36, 5402540.18, -424.27],width: 20.0,height:20,direction:[0,1,1] };
-   
-  // const triangleFilter = vtkTriangleFilter.newInstance();
-  const shapeSource2 = vtk2DShape.newInstance(initialValues);
-  // triangleFilter.setInputConnection(shapeSource2.getOutputPort());
-
-  const mapper2 = vtkMapper.newInstance();
-  mapper2.setInputConnection(shapeSource2.getOutputPort());
-  const actor2 = vtkActor.newInstance();
-  actor2.setMapper(mapper2);
-  renderer.addActor(actor2);
-
-  // const cubeAxes = vtkCubeAxesActor.newInstance();
-  // cubeAxes.setCamera(renderer.getActiveCamera());
-  // cubeAxes.setDataBounds(actor1.getBounds());
-  // renderer.addActor(cubeAxes);
-
-
-  // const axesActor = vtkAxesActor.newInstance();
-  // renderer.addActor(axesActor);
-
-
-
-  renderer.resetCamera();
-  renderWindow.render();
-  fireRead();
-});
-
-function fireRead() {
-  var fcon = createFireControl();
-  fcon
-    .initGemetry()
-    .then((result) => {
-      fcon
-        .initScalrs()
-        .then((result) => {
-         // console.log(fcon.scalars)
-          const scalarArray = fcon.scalars[3].get("Pressure");
-          //console.log("scalarArray:", scalarArray);
-          const dataArray = vtkDataArray.newInstance({ 
-            name: arrvalue[1],
-            size: fcon.polydata.getNumberOfPoints(),
-          });
-          console.log(dataArray)
-          dataArray.setData(scalarArray);
-          fcon.polydata.getPointData().setScalars(dataArray);
-          mapper.setInputData(fcon.polydata);
-          getMinMax(scalarArray);
-          mapper.setScalarRange(min.value, max.value); //设置范围
-          actor.setMapper(mapper);
-          renderer.addActor(actor);
-
-          initScalarBar();
-          renderer.resetCamera();
-          renderWindow.render();
-        })
-        .catch((err) => {});
-    })
-    .catch((err) => {});
-}
-
-// 初始化 bar
-function initScalarBar() {
-  const scalarBarActor = vtkScalarBarActor.newInstance();
-  let lut = mapper.getLookupTable();
-  scalarBarActor.setScalarsToColors(lut);
-  // console.log("lut:", lut.getRange());
-  // Change the number of ticks (TODO: add numberOfTicks to ScalarBarActor)
-  scalarBarActor.setGenerateTicks(generateTicks(5));
-  scalarBarActor.setAxisLabel(arrvalue[1]);
-  scalarBarActor.setDrawAboveRangeSwatch(true);
-  //修改设条颜色
-  const ctf = vtkColorTransferFunction.newInstance();
-  ctf.addRGBPoint(0.0, 0.0, 0.0, 1.0);
-  ctf.addRGBPoint(1.0, 0.0, 1.0, 0.5);
-  ctf.addRGBPoint(2.0, 0.0, 1.0, 0.0);
-  ctf.addRGBPoint(3.0, 1.0, 0.5, 0.0);
-  ctf.addRGBPoint(4.0, 1.0, 0.0, 0.0);
-  mapper.setLookupTable(ctf);
-  lut = mapper.getLookupTable();
-  scalarBarActor.setScalarsToColors(lut);
-  renderer.addActor(scalarBarActor);
-}
-defineExpose({changeScalar})
-</script>
-
-<style>
-#vtkContainer{
-  position: relative;
-}
-.vtk{
-  position: relative;
-}
-.controls {
-  position: absolute;
-  top: 25px;
-  left: 25px;
-  background: white;
-  padding: 12px;
-}
-.haha {
-  color: #fff;
-}
-.tool {
-  position: fixed;
-  top: 50px;
-  left: 20px;
-
-  z-index: 205;
-}
-.img {
-  width: 48px;
-  margin: -6px 0;
-  padding: 8px 10px;
-  background-color: rgba(255, 255, 255, 0.1);
-  font-size: 12px;
-  transform: scale(0.9);
-}
-.img span {
-  color: #fff;
-  display: inline-block;
-}
-.img .el-image {
-  width: 34px;
-}
-.leftdialong {
-  padding: 15px;
-  width: 300px;
-  position: relative;
-  top: -248px;
-  left: 69px;
-  border-radius: 5px;
-  box-shadow: 0px 3px 10px rgba(255, 255, 255, 0.1);
-}
-.leftdialong .el-form-item__label {
-  font-size: 12px;
-  color: #fff !important;
-  padding-left: 6px;
-}
-.time {
-  color: #fff;
-  font-size: 12px;
-  margin-bottom: 30px;
-}
-.itemlist {
-  display: flex;
-}
-.item {
-  background-color: rgba(255, 255, 255, 0.1);
-  margin: 5px;
-  padding: 5px 9px;
-  border-radius: 5px;
-  font-size: 14px;
-  transform: scale(0.8);
-  color: #fff;
-}
-.dialog-footer {
-  margin-top: 30px;
-  text-align: right;
-}
-.block {
-  display: flex;
-}
-.demonstration {
-  padding: 5px 5px 5px 0;
-  font-size: 12px;
-  color: #fff;
-  display: inline-block;
-  width: 100px;
-  height: 24px;
-  line-height: 24px;
-}
-.block .el-slider {
-  padding: 0 5px;
-}
-.cascadeer .el-cascader {
-  width: 100%;
-}
-.cascadeer .asterisk-left {
-  width: 100% !important;
-  font-size: 12px;
-}
-.btn {
-  background-color: rgba(255, 255, 255, 0.1);
-  margin: 5px;
-  padding: 5px 9px;
-  border-radius: 5px;
-  font-size: 14px;
-  transform: scale(0.8);
-  color: #fff;
-}
-</style>
+  </style>
+  

+ 414 - 0
src/view/vtkContainer2.vue

@@ -0,0 +1,414 @@
+<template>
+    <div class="vtk">
+        <!-- <div id="vtkContainer" /> -->
+    
+      </div>
+    
+    </template>
+    
+    <script setup>
+    
+    import * as d3 from "d3-scale";
+    import { formatDefaultLocale } from "d3-format";
+    import { ref, onMounted, reactive } from "vue";
+    import "@kitware/vtk.js/Rendering/Profiles/Geometry";
+    import vtkRenderWindowWithControlBar from "@kitware/vtk.js/Rendering/Misc/RenderWindowWithControlBar";
+    import vtkFullScreenRenderWindow from "@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow";
+    
+    import vtkActor from "@kitware/vtk.js/Rendering/Core/Actor";
+    import vtkMapper from "@kitware/vtk.js/Rendering/Core/Mapper";
+    import vtkUnstructuredDataReader from "../reader/UnstructuredDataReader.js";
+    import { createFireControl } from "../control/fireControl.js";
+    import vtkScalarBarActor from "@kitware/vtk.js/Rendering/Core/ScalarBarActor";
+    import vtkLookupTable from "@kitware/vtk.js/Common/Core/LookupTable";
+    import vtkDataArray from "@kitware/vtk.js/Common/Core/DataArray.js";
+    import vtkColorTransferFunction from "@kitware/vtk.js/Rendering/Core/ColorTransferFunction";
+    import { I } from "@kitware/vtk.js/macros2.js";
+    import { Representation } from "@kitware/vtk.js/Rendering/Core/Property/Constants";
+    import evolutionView from "./evolutionView.vue";
+    
+    import vtkConeSource from "@kitware/vtk.js/Filters/Sources/ConeSource";
+    import vtkSphereMapper from "@kitware/vtk.js/Rendering/Core/SphereMapper";
+    import vtkPixelSpaceCallbackMapper from "@kitware/vtk.js/Rendering/Core/PixelSpaceCallbackMapper";
+    import vtkSphereSource from "@kitware/vtk.js/Filters/Sources/SphereSource";
+    
+    import vtkAxesActor from "@kitware/vtk.js/Rendering/Core/AxesActor";
+    import vtkCubeAxesActor from "@kitware/vtk.js/Rendering/Core/CubeAxesActor";
+    import vtk2DShape from '@kitware/vtk.js/Filters/Sources/Arrow2DSource';
+    import vtkTriangleFilter from '@kitware/vtk.js/Filters/General/TriangleFilter';
+    // const props = {};
+    let time = 3 * 60;
+    const props= defineProps({
+      vatkval:{
+            type: Object,
+        },
+        arrvalue:{
+          type: Array,
+         
+        }
+     });
+    // let title1=ref("我是父组件")
+    let dialogVisible = ref(false);
+    // let num = ref(4);
+    // let starttime = ref(1);
+    // let endtime = ref(60);
+    // let timenum = ref(2);
+    // let isstop = ref(false);
+     let arrvalue = reactive([]);
+    
+    // 响应式状态
+    const count = ref(0);
+    const opacity = ref(0.1);
+    const min = ref(0);
+    const max = ref(1);
+    const scalarFAll = ref([]); //火灾标量
+    const scalarWAll = ref([]); //水灾标量
+    /*
+    Temperature:温度
+    Pressure:压强
+    SO2:SO2
+    CO2:CO2
+    Height:水位高度
+    */
+    // const scalarName = ref("CO2");
+    //  const filedir =ref("data/Fire/");
+    //const scalarName = ref("Height");
+    const filedir = ref("data/Water/");
+    // const renderWindowWith = vtkRenderWindowWithControlBar.newInstance({
+    //     controlSize: 11,
+    //   });
+    
+    const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance();
+    const renderer = fullScreenRenderer.getRenderer();
+    const renderWindow = fullScreenRenderer.getRenderWindow();
+    const mapper = vtkMapper.newInstance();
+    const actor = vtkActor.newInstance();
+    
+    // actor.getProperty().setRepresentation(Representation.WIREFRAME);//线
+    // actor.getProperty().setRepresentation(Representation.POINTS);//点
+    actor.getProperty().setRepresentation(Representation.SURFACE); //面
+    
+    // 用来修改状态、触发更新的函数
+    function inOpacity() {
+      opacity.value = opacity.value + 0.1;
+      actor.getProperty().setOpacity(opacity.value);
+      renderWindow.render();
+    }
+    function getMinMax(scalars) {
+      // console.log("getMinMax:",scalars);
+      min.value = scalars[0];
+      max.value = scalars[0];
+      for (let index = 0; index <= scalars.length; index++) {
+        let scalar = scalars[index];
+        if (min.value > scalar) {
+          min.value = scalar;
+        }
+        if (max.value < scalar) {
+          max.value = scalar;
+        }
+      }
+      // console.log("max,min:", max.value, min.value);
+    }
+    //时间
+    function sleep(numberMillis) {
+      var now = new Date();
+      var exitTime = now.getTime() + numberMillis;
+      console.log(exitTime);
+    }
+    
+    
+    
+    
+    
+    // 用来修改状态、触发更新的函数
+    function increment() {
+      isstop.value = false;
+      if (count.value == endtime.value) {
+        return;
+      }
+      count.value++;
+      changeScalar();
+    }
+    function changeScalar() {
+      console.log(props.arrvalue)
+      var scalars;
+      if (props.arrvalue[0] == "fire") {
+        scalars = scalarFAll.value[count.value];
+      } else {
+        scalars = scalarWAll.value[count.value];
+      }
+      const polydata = mapper.getInputData();
+      const scalarArray = scalars.get(props.arrvalue[1]);
+      // console.log("scalarArray:", scalarArray);
+      const dataArray = vtkDataArray.newInstance({
+        name: props.arrvalue[1],
+        size: polydata.getNumberOfPoints(),
+      });
+      dataArray.setData(scalarArray);
+      getMinMax(scalarArray);
+      mapper.setScalarRange(min.value, max.value); //设置范围
+      scalarBarActor.setAxisLabel(props.arrvalue[1]);
+      polydata.getPointData().setScalars(dataArray);
+      mapper.clearColorArrays(); //强制重建颜色
+      actor.getProperty().setOpacity(count.value); //设置错误的透明度使得页面重新加载  不设置不刷新页面
+      renderWindow.render();
+    }
+    //加载所有 标量数据
+    function loadScalarAll() {
+      //水灾
+      // for (let index = 0; index <= 15; index++) {
+        //   const reader = vtkUnstructuredDataReader.newInstance();
+      //   const url="http://192.168.0.131:8187/TransServlet?channelNo=service&clientToken=e47b87eec69545559d1e81e56626da68&transCode=D00009&userId=5f06c8bc77234f969d13e160b54c27e3&aid=5&stype=Water&step="
+      //   reader.setUrl(url + index ).then(() => {
+      //     const scalars = reader.getOutputData(1);
+      //     scalarWAll.value[index] = scalars;
+      //   });
+      // }
+      //火灾
+      for (let index = 1; index <= 4; index++) {
+        const reader = vtkUnstructuredDataReader.newInstance();
+        const url =
+          "http://192.168.0.131:8187/TransServlet?channelNo=service&clientToken=e47b87eec69545559d1e81e56626da68&transCode=D00009&userId=5f06c8bc77234f969d13e160b54c27e3&aid=5&stype=Fire&step=";
+        reader.setUrl(url + index).then(() => {
+          console.log("url + index ", index);
+          const scalars = reader.getOutputData(1);
+          scalarFAll.value[index] = scalars;
+          console.log(scalars);
+          console.log(2222)
+          console.log("url end  ");
+        });
+      }
+      console.log("scalarAll.value:", scalarFAll);
+    }
+    //设置
+    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);
+      };
+    }
+    //安装时
+    onMounted(() => {
+      arrvalue = ["Water", "Height"];
+      // const sphereSource = vtkSphereSource.newInstance({
+      //   center: [495960.36, 5402540.18, -424.27],
+      //   radius: 3.02,
+      //   phiResolution: 20,
+      //   thetaResolution:20,
+      // });
+    
+      // const mapper1 = vtkMapper.newInstance();
+      // mapper1.setInputConnection(sphereSource.getOutputPort());
+      // const actor1 = vtkActor.newInstance();
+      // actor1.setMapper(mapper1);
+      // actor1.getProperty().setColor([0.95, 0.45, 0.95]);
+      // renderer.addActor(actor1);
+    
+    // choices include triangle, star, arrow4points, arrow6points
+      const initialValues = { base:-0.1,shape: 'arrow4points',center: [495960.36, 5402540.18, -424.27],width: 20.0,height:20,direction:[0,1,1] };
+       
+      // const triangleFilter = vtkTriangleFilter.newInstance();
+      const shapeSource2 = vtk2DShape.newInstance(initialValues);
+      // triangleFilter.setInputConnection(shapeSource2.getOutputPort());
+    
+      const mapper2 = vtkMapper.newInstance();
+      mapper2.setInputConnection(shapeSource2.getOutputPort());
+      const actor2 = vtkActor.newInstance();
+      actor2.setMapper(mapper2);
+      renderer.addActor(actor2);
+    
+      // const cubeAxes = vtkCubeAxesActor.newInstance();
+      // cubeAxes.setCamera(renderer.getActiveCamera());
+      // cubeAxes.setDataBounds(actor1.getBounds());
+      // renderer.addActor(cubeAxes);
+    
+    
+      // const axesActor = vtkAxesActor.newInstance();
+      // renderer.addActor(axesActor);
+    
+    
+    
+      renderer.resetCamera();
+      renderWindow.render();
+      fireRead();
+    });
+    
+    function fireRead() {
+      var fcon = createFireControl();
+      fcon
+        .initGemetry()
+        .then((result) => {
+          fcon
+            .initScalrs()
+            .then((result) => {
+             // console.log(fcon.scalars)
+              const scalarArray = fcon.scalars[3].get("Pressure");
+              //console.log("scalarArray:", scalarArray);
+              const dataArray = vtkDataArray.newInstance({ 
+                name: arrvalue[1],
+                size: fcon.polydata.getNumberOfPoints(),
+              });
+              console.log(dataArray)
+              dataArray.setData(scalarArray);
+              fcon.polydata.getPointData().setScalars(dataArray);
+              mapper.setInputData(fcon.polydata);
+              getMinMax(scalarArray);
+              mapper.setScalarRange(min.value, max.value); //设置范围
+              actor.setMapper(mapper);
+              renderer.addActor(actor);
+    
+              initScalarBar();
+              renderer.resetCamera();
+              renderWindow.render();
+            })
+            .catch((err) => {});
+        })
+        .catch((err) => {});
+    }
+    
+    // 初始化 bar
+    function initScalarBar() {
+      const scalarBarActor = vtkScalarBarActor.newInstance();
+      let lut = mapper.getLookupTable();
+      scalarBarActor.setScalarsToColors(lut);
+      // console.log("lut:", lut.getRange());
+      // Change the number of ticks (TODO: add numberOfTicks to ScalarBarActor)
+      scalarBarActor.setGenerateTicks(generateTicks(5));
+      scalarBarActor.setAxisLabel(arrvalue[1]);
+      scalarBarActor.setDrawAboveRangeSwatch(true);
+      //修改设条颜色
+      const ctf = vtkColorTransferFunction.newInstance();
+      ctf.addRGBPoint(0.0, 0.0, 0.0, 1.0);
+      ctf.addRGBPoint(1.0, 0.0, 1.0, 0.5);
+      ctf.addRGBPoint(2.0, 0.0, 1.0, 0.0);
+      ctf.addRGBPoint(3.0, 1.0, 0.5, 0.0);
+      ctf.addRGBPoint(4.0, 1.0, 0.0, 0.0);
+      mapper.setLookupTable(ctf);
+      lut = mapper.getLookupTable();
+      scalarBarActor.setScalarsToColors(lut);
+      renderer.addActor(scalarBarActor);
+    }
+    defineExpose({changeScalar})
+    </script>
+    
+    <style>
+    #vtkContainer{
+      position: relative;
+    }
+    .vtk{
+      position: relative;
+    }
+    .controls {
+      position: absolute;
+      top: 25px;
+      left: 25px;
+      background: white;
+      padding: 12px;
+    }
+    .haha {
+      color: #fff;
+    }
+    .tool {
+      position: fixed;
+      top: 50px;
+      left: 20px;
+    
+      z-index: 205;
+    }
+    .img {
+      width: 48px;
+      margin: -6px 0;
+      padding: 8px 10px;
+      background-color: rgba(255, 255, 255, 0.1);
+      font-size: 12px;
+      transform: scale(0.9);
+    }
+    .img span {
+      color: #fff;
+      display: inline-block;
+    }
+    .img .el-image {
+      width: 34px;
+    }
+    .leftdialong {
+      padding: 15px;
+      width: 300px;
+      position: relative;
+      top: -248px;
+      left: 69px;
+      border-radius: 5px;
+      box-shadow: 0px 3px 10px rgba(255, 255, 255, 0.1);
+    }
+    .leftdialong .el-form-item__label {
+      font-size: 12px;
+      color: #fff !important;
+      padding-left: 6px;
+    }
+    .time {
+      color: #fff;
+      font-size: 12px;
+      margin-bottom: 30px;
+    }
+    .itemlist {
+      display: flex;
+    }
+    .item {
+      background-color: rgba(255, 255, 255, 0.1);
+      margin: 5px;
+      padding: 5px 9px;
+      border-radius: 5px;
+      font-size: 14px;
+      transform: scale(0.8);
+      color: #fff;
+    }
+    .dialog-footer {
+      margin-top: 30px;
+      text-align: right;
+    }
+    .block {
+      display: flex;
+    }
+    .demonstration {
+      padding: 5px 5px 5px 0;
+      font-size: 12px;
+      color: #fff;
+      display: inline-block;
+      width: 100px;
+      height: 24px;
+      line-height: 24px;
+    }
+    .block .el-slider {
+      padding: 0 5px;
+    }
+    .cascadeer .el-cascader {
+      width: 100%;
+    }
+    .cascadeer .asterisk-left {
+      width: 100% !important;
+      font-size: 12px;
+    }
+    .btn {
+      background-color: rgba(255, 255, 255, 0.1);
+      margin: 5px;
+      padding: 5px 9px;
+      border-radius: 5px;
+      font-size: 14px;
+      transform: scale(0.8);
+      color: #fff;
+    }
+    </style>
+