vtk坐标系,以人体为例:
x 轴正向: 从右至左 [1,0,0],反向:从左至右[-1,0,0]
y轴正向:从前至后[0,1,0],反向:从后至前[0,-1,0]
z轴正向:从下至上[0,0,1],反向:从上至下[0,0,-1]
相机的两个参数:
于是可得以下参数:
前视( A ): viewPlaneNormal即为y轴反向[0, -1, 0],viewUp z轴正向[0,0,1]
后视( P ): viewPlaneNormal即为y轴正向[0, 1, 0],viewUp z轴正向[0,0,1]
左视( L ): viewPlaneNormal即为x轴正向[1, 0, 0],viewUp z轴正向[0,0,1]
右视( R ): viewPlaneNormal即为x轴反向[-1, 0, 0],viewUp z轴正向[0,0,1]
俯视( S ): viewPlaneNormal即为z轴正向[0, 0, 1],viewUp y轴正向[0,1,0]或反向[0,-1,0]
仰视( I ): viewPlaneNormal即为z轴反向[0, 0, -1],viewUp y轴反向[0,-1,0]
const cameraPos = {
A: {
viewPlaneNormal: [0, -1, 0],
viewUp: [0, 0, 1]
},
P: {
viewPlaneNormal: [0, 1, 0],
viewUp: [0, 0, 1]
},
L: {
viewPlaneNormal: [1, 0, 0],
viewUp: [0, 0, 1]
},
R: {
viewPlaneNormal: [-1, 0, 0],
viewUp: [0, 0, 1]
},
S: {
viewPlaneNormal: [0, 0, 1],
viewUp: [0, 1, 0]
},
I: {
viewPlaneNormal: [0, 0, -1],
viewUp: [0, -1, 0]
}
};
export default class MPR {
...
setCameraPosition(position) {
// 获取相机位置参数
const data = cameraPos[position];
const viewport = this.renderingEngine.getViewport(idVolume);
// 设置相机位置参数
viewport.setCamera({
viewUp: data.viewUp,
viewPlaneNormal: data.viewPlaneNormal
});
viewport.resetCamera();
}
}
<script setup name="Toolbar3D">
const cameraPos = [
{name:"前视(A)", value: "A"},
{name:"后视(P)", value: "P"},
{name:"左视(L)", value: "L"},
{name:"右视(R)", value: "R"},
{name:"俯视(S)", value: "S"},
{name:"仰视(I)", value: "I"},
];
const currentCameraPos = ref("A");
watch(currentCameraPos, (newValue) => {
emit("action", { name: "changeCameraPos", value: newValue });
});
</script>
<template>
...
<div class="toolbar-row">
<div class="pre-label">Camera:</div>
<el-select v-model="currentCameraPos" placeholder="Select Camera Position" style="width: 200px">
<el-option v-for="item in cameraPos" :key="item.value" :label="item.name" :value="item.value" />
</el-select>
</div>
</template>
在OnToolbarAction中添加事件响应
async function OnToolbarAction(action) {
...
case "changeCameraPos":
displayArea.value.setCameraPosition(action.value);
break;
}
添加并导出函数setCameraPosition
const setCameraPosition = position => {
theMPR.setCameraPosition(position);
};
defineExpose({
...
setCameraPosition
});
VR视图:
切片视图:
3. 调用viewport.resetCamera()
4. 设置默认窗宽窗位
修改mprvr.js,在loadImages函数中保存相机初始参数。增加resetCamera函数
const initVolumeCamera = {
viewUp: [],
viewPlaneNormal: [],
position: [],
focalPoint: [],
viewAngle: 0,
parallelScale: 1
};
export default class MPR {
...
async loadImages(imageIds) {
...
this.renderingEngine.renderViewports(viewportIds);
const viewport = this.renderingEngine.getViewport(idVolume);
await setVolumesForViewports(this.renderingEngine, [{ volumeId }], [idVolume]).then(() => {
viewport.setProperties({
preset: "CT-Coronary-Arteries-2"
});
// 保存相机初始参数
const camera = viewport.getCamera();
initVolumeCamera.viewUp = camera.viewUp;
initVolumeCamera.viewPlaneNormal = camera.viewPlaneNormal;
initVolumeCamera.position = camera.position;
initVolumeCamera.focalPoint = camera.focalPoint;
initVolumeCamera.viewAngle = camera.viewAngle;
initVolumeCamera.parallelScale = camera.parallelScale;
});
...
}
resetCamera() {
if (!this.loaded) return;
viewportIds.forEach(viewportId => {
const viewport = this.renderingEngine.getViewport(viewportId);
if (viewport) {
if (viewportId === idVolume) { // VR视图
// 设置默认preset
viewport.setProperties({
preset: "CT-Coronary-Arteries-2"
});
// 设置初始相机参数
const camera = viewport.getCamera();
camera.viewUp = initVolumeCamera.viewUp;
camera.viewPlaneNormal = initVolumeCamera.viewPlaneNormal;
camera.position = initVolumeCamera.position;
camera.focalPoint = initVolumeCamera.focalPoint;
camera.viewAngle = initVolumeCamera.viewAngle;
camera.parallelScale = initVolumeCamera.parallelScale;
viewport.setCamera(camera);
} else { // 切片视图
viewport.resetCamera();
viewport.render();
}
}
});
}
}
// defWW, defWL在load函数中保存了默认窗值
const setDefaultWindow = () => {
theMPR.setWindow(defWW.value, defWL.value);
};
const reset = () => {
theMPR.resetCamera();
setDefaultWindow();
};
defineExpose({
...
reset
});
1.讲解VR视图六个正向视图的相机参数是如何设置的
2.VR视图与切片视图复位