Skip to content

XCircleCenterWidget

简介

通过一个圆来定义一个中心,其中心和圆周上的点都可以交互。圆周的点用于改变半径,中心点用于平移。

XCircleCenterWidget

主要方法

  • 获取圆心世界坐标。
  • 获取圆周控制点世界坐标。
  • 获取当前圆的半径。
  • 设置圆心(若圆尚未存在则创建默认半径的圆,否则整体平移)。
  • 通过圆心和半径设置圆。
  • 设置圆心控制点颜色 [R, G, B] 0–255。
  • 设置圆周控制点颜色 [R, G, B] 0–255。
  • 设置控制点激活(hover)颜色。
  • 设置所有 handle 的缩放因子(世界坐标单位)。
  • setHandleScale 的别名,与其完全等价。
  • 设置圆边线颜色。
  • 设置边线激活颜色。
  • 设置边线宽度(像素)。
  • 设置虚线段长度(0 = 自动)。
  • 设置虚线间距(0 = 自动)。
  • 重置 widget 到初始状态。
  • 放置/移动开始时触发。
  • 拖拽过程中持续触发。
  • 放置/移动结束时触发。

使用演示

vue
<template>
  <div
    style="
      display: flex;
      flex-direction: column;
      gap: 10px;
      padding: 10px;
      height: calc(100vh - 120px);
    "
  >
    <!-- 工具栏 -->
    <div style="display: flex; gap: 8px; flex-wrap: wrap; align-items: center">
      <button @click="startPlace">开始绘制圆形</button>
      <button @click="resetWidget">重置</button>
      <span
        v-if="info"
        style="
          padding: 4px 8px;
          background: #1a1a2e;
          color: #42b883;
          border-radius: 4px;
          font-size: 12px;
        "
      >
        圆心: {{ info.center }} | 半径: {{ info.radius }}
      </span>
    </div>

    <!-- 提示文字 -->
    <div style="font-size: 12px; color: #888; line-height: 1.6">
      左键按下定义圆心,拖动并释放定义圆的大小 · 圆心点可整体平移 ·
      圆周控制点可调整大小
    </div>

    <!-- 3D 视图 -->
    <XView3D
      ref="view3D"
      viewID="xcirclecenter-widget-demo"
      :background="[0.08, 0.08, 0.12, 1]"
      style="flex: 1; border: 2px solid #42b883; border-radius: 4px"
    />
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted, onBeforeUnmount } from "vue";
import XView3D from "@/components/XView3D.vue";
import vtkWidgetManager from "@kitware/vtk.js/Widgets/Core/WidgetManager";
// @ts-ignore —— XCircleCenterWidget 是 JS 模块,通过 index.d.ts 提供类型
import XCircleCenterWidget from "@/widgets/XCircleCenterWidget/index.js";

// ── 组件状态 ──────────────────────────────────────────────────────────────────
const view3D = ref<InstanceType<typeof XView3D> | null>(null);
const info = ref<{ center: string; radius: string } | null>(null);

let widgetManager: ReturnType<typeof vtkWidgetManager.newInstance> | null =
  null;
let widget: ReturnType<typeof XCircleCenterWidget.newInstance> | null = null;
let widgetView: any = null;

// ── 初始化 ────────────────────────────────────────────────────────────────────
onMounted(() => {
  if (!view3D.value) return;

  const renderer = view3D.value.getRenderer();
  const renderWindow = view3D.value.getRenderWindow();

  // ① 创建 WidgetManager
  widgetManager = vtkWidgetManager.newInstance();
  widgetManager!.setRenderer(renderer);

  // ② 创建 XCircleCenterWidget
  widget = XCircleCenterWidget.newInstance({
    activeColor: [255, 120, 0],
    activeScaleFactor: 1.4,
    handleScale: 0.1,
    lineThickness: 2,
    lineColor: [0, 230, 255],
  });

  // ③ 注册到场景
  widgetView = widgetManager!.addWidget(widget as any);

  // ④ 监听交互事件
  widgetView?.onEndInteractionEvent(() => {
    const origin = widget!.getCenterOrigin();
    const radius = widget!.getRadius();
    if (origin) {
      info.value = {
        center: origin.map((v) => v.toFixed(2)).join(", "),
        radius: radius.toFixed(2),
      };
    }
    renderer.getActiveCamera().setClippingRange(1, 10000);
    renderWindow.render();
  });

  // ⑤ 进入放置模式
  widgetManager!.grabFocus(widget as any);

  renderer.resetCamera();
  renderWindow.render();
});

onBeforeUnmount(() => {
  widgetManager?.delete();
});

// ── 按钮操作 ──────────────────────────────────────────────────────────────────

function startPlace() {
  resetWidget();
  widgetManager!.grabFocus(widget as any);
}

function resetWidget() {
  widget!.reset();
  info.value = null;
  widgetManager!.grabFocus(widget as any);
}
</script>