Appearance
主要构成
主要组件
库目前主要分为以下三部分:
- 视图类
- IO 类
- 工具类
其中,视图类是本库最核心的部分,分为二维视图和三维视图。二维视图主要用于显示图像,三维视图主要用于显示三维模型;IO 类用于解析各类文件,如医学图像里的 DICOM 图像,三维模型里的 STL,以及其他常见的 PNG、JPG 或是 .nii.gz 等;工具类用于提供各类静态函数,方便开发者获取定义各类数据,如点、线、框等类型。
此外,在 v0.0.12 后,增加了 4 个 Widget,分别是 XPointWidget、XLineWidget、XRectCenterWidget 和 XCircleCenterWidget。这 4 个 Widget 可以用于定义中心、长度、范围等信息,具体用法见 交互 Widget。
视图类
三维视图
三维视图,顾名思义,是一个用于构建三维空间的组件。它的使用很简单,直接在 Vue 页面中引入该组件,并在 template 中使用就可以。下面的代码是一个示例。
vue
<template>
<XView3D
ref="view3D"
viewID="vtk-container2"
:background="[0.0, 0.0, 0.0, 1]"
style="width: 500px; height: 800px"
/>
</template>
<script setup lang="ts">
import XView3D from "@/components/XView3D.vue";
import { ref, onMounted } from "vue";
const view3D = ref<InstanceType<typeof XView3D> | null>(null);
</script>主要的属性
ref,模板引用,字符串类型,可通过view3D.value的方式直接调用组件的方法background,背景颜色,如[0.0, 0.0, 0.0, 1]表示黑色width,视图的宽度height,视图的高度style,视图的样式viewID,视图的 ID,可在调试或者页面分析时用 id 进行查找、设置特殊样式,字符串类型
回调函数
以下为主要的回调函数,在组件中通过类似 @onPropWheel="..." 的方式应用,其中值为在组件部分中定义的方法:
- 鼠标在模型上滚动触发
- 鼠标滑动进入模型
- 鼠标滑动离开模型
- 鼠标左键按下模型
- 鼠标左键按下抬起模型
- 鼠标左键按下移动模型
- 鼠标按下移动抬起模型
直接函数
以下为主要的直接函数,在组件内使用 view3D.value?.xxx() 来进行调用:
获得 renderWindow
获得 renderer
获得 interactor
获得 interactorStyle
在 300ms 内只执行一次渲染操作
无视节流限制,直接刷新渲染结果
将渲染器的相机重置为默认视图
屏幕坐标转换为世界坐标
投影世界坐标到焦平面
获得某个 actor 的 name
添加一个模型 actor,其中
propActorProperty定义如下:tsexport interface propActorProperty { /** Actor 的颜色,使用 RGB 格式。 */ color?: RGBColor; /** Actor 的透明度,范围从 0.0(完全透明)到 1.0(完全不透明)。 */ opacity?: number; /** Actor 的可见性,true 表示可见,false 表示不可见。 */ visibility?: boolean; /** Actor 的线宽度。 */ lineWidth?: number; /** Actor 是否可拾取。 */ pickable?: boolean; }添加一个图像 actor,其中
MPROrientation的定义如下:tsexport type MPROrientation = "axial" | "sagittal" | "coronal";添加分割 actor:
tsaddSegmentation: ( segName: string, orientation: MPROrientation, linkedImageName?: string, opacity?: number, colorMap?: LabelColorMap, ) => XSegmentationActor;segName分割图在 XDataStore 中的名称;orientation切片方向(axial / sagittal / coronal);linkedImageName要绑定切片平面的底层图像名称(可选);opacity覆盖层透明度(0-1),默认 0.5;colorMap自定义标签颜色表(可选)。获取指定名称的分割 actor
移除一个分割 actor
移除所有分割 actor
切换视图内所有图像 actor 和分割 actor 的切片方向,并更新相机
同步更新视图内所有图像 actor 和分割 actor 的切片位置
二维视图
二维视图与三维视图的内容基本一致。
IO 类
用于读取各类文件,如 DICOM 图像、STL 文件等。
readDICOM
读取 DICOM 图像的返回结果是 DicomReadResult,其定义如下:
ts
export interface DicomReadResult {
/** VTK ImageData,可直接用于渲染 */
imageData: vtkImageData;
/** 原始 itk-wasm Image,包含完整元数据 */
itkImage: Image;
/** 排序后的文件名列表 */
sortedFilenames: object;
/** 序列首文件的全部 DICOM Tag,每项为 [tag, value],如 ["0010|0010", "张三"] */
tags: Array<[string, string]>;
}读取 DICOM tag 的返回结果是 DicomTagsResult,其定义如下:
ts
export interface DicomTagsResult {
/** Tag 键值对数组,每项为 [tag, value],如 ["0010|0010", "张三"] */
tags: Array<[string, string]>;
}读取 tag
- 读取单个 DICOM 文件的 Tag 信息,
file为单个 DICOM File 对象,tagKeywords为可选,如["PatientName", "SeriesInstanceUID"];不传则读取全部 - 从 ArrayBuffer 读取单个 DICOM 文件的 Tag 信息,
data为文件二进制内容,path为文件名(如"slice.dcm"),tagKeywords同上
序列分组
将一组 DICOM File 按 SeriesInstanceUID 分组。
读取图像
- 读取一组 DICOM 文件(同一序列),
files来自<input type="file">的 File 对象数组,singleSortedSeries文件是否已按序列顺序排好,默认 false(由库自动排序) files为数组,path仅用于排序,填文件名即可
readNifti
读取 nifti 文件后返回的结果为 NiftiReadResult,其定义如下:
ts
export interface NiftiReadResult {
/** VTK ImageData,可直接用于渲染 */
imageData: vtkImageData;
/** 原始 itk-wasm Image,包含完整元数据(spacing、direction、origin 等) */
itkImage: Image;
}- 从浏览器 File 对象读取 NIfTI 文件
- 从 ArrayBuffer / Uint8Array 读取 NIfTI 数据
readImage
读取 image 后,返回的结果为 ReadImageResult,其定义如下:
ts
export interface ReadImageResult {
/** VTK ImageData,可直接用于渲染 */
imageData: vtkImageData;
/** 原始 itk-wasm Image,包含完整元数据(spacing、origin、direction 等) */
itkImage: Image;
}- 从浏览器 File 对象读取图像
- 从 Uint8Array 读取图像
readSTL
从文件中读取 STL 模型。
readObj
从文件中读取 OBJ 模型。
工具类
工具类主要是提供一些静态函数,供开发人员调用获取数据的接口。目前支持的有以下三种:
createFrame用于创建矩形createLine用于创建直线createPoint用于创建点
使用示例
vue
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { XDataStore } from "@/data/XDataStore";
import type { Vector3 } from "@kitware/vtk.js/types.d.ts";
import { createLine } from "@/utils/createLine";
import { createPoint } from "@/utils/createPoint";
import { createFrame } from "@/utils/createFrame";
onMounted(() => {
XDataStore.getInstance()
.addPropData("test")
.add(createLine.line([0, 0, 0], [1, 1, 1]))
.add(createLine.dashedLine([0, 0, 0], [10, 0, 0]))
.add(createPoint.point([0, 0, 0], 0.1))
.add(createPoint.crossPoint([1, 1, 1], 0.1))
.add(createFrame.frame([0, 0, 0], [1, 1, 1]))
.print();
});
</script>createPoint
- 创建一个点,
radius点的半径,thetaResolution点的经向分辨率,phiResolution点的纬向分辨率 - 创建一个十字形的点,由三条线段组成,分别沿 x、y、z 轴方向
createLine
- 创建一条线段,连接两个点 p1 和 p2
- 创建虚线,由
numSegments段等间距短线组成
createFrame
- 创建一个矩形框架,由四条线段组成,连接
leftTop和rightBottom定义的两个对角点 - 创建一个虚线矩形框架,由四条虚线段组成,连接
leftTop和rightBottom定义的两个对角点,numSegments每条边的虚线段数,默认为 10