@cornerstonejs/core
Version:
Cornerstone3D Core
157 lines (156 loc) • 5.41 kB
JavaScript
import '@kitware/vtk.js/Rendering/Profiles/Geometry.js';
import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor.js';
import vtkMapper from '@kitware/vtk.js/Rendering/Core/Mapper.js';
import vtkPolyData from '@kitware/vtk.js/Common/DataModel/PolyData.js';
import vtkCellArray from '@kitware/vtk.js/Common/Core/CellArray.js';
import { GeometryType, ViewportType } from '../../../enums/index.js';
import uuidv4 from '../../../utilities/uuidv4.js';
import { canvasToWorldContextPool, worldToCanvasContextPool, } from '../../helpers/vtkCanvasCoordinateTransforms.js';
import applyVolume3DCamera from './applyVolume3DCamera.js';
export class VtkGeometry3DRenderPath {
async addData(ctx, data, options) {
const payload = data;
const actors = createActorEntries(payload.geometry);
const hadVisibleProps = hasVisibleProps(ctx);
actors.forEach((actorEntry) => {
ctx.vtk.renderer.addActor(actorEntry.actor);
});
if (!hadVisibleProps) {
ctx.vtk.renderer.resetCamera();
}
ctx.vtk.renderer.resetCameraClippingRange();
const rendering = {
renderMode: 'vtkGeometry3d',
actors,
frameOfReferenceUID: payload.geometry.type === GeometryType.SURFACE
? payload.geometry.data.frameOfReferenceUID
: undefined,
};
return {
rendering,
updateDataPresentation: (props) => {
this.updateDataPresentation(rendering, props);
},
applyViewState: (camera) => {
this.applyViewState(ctx, camera);
},
getFrameOfReferenceUID: () => {
return this.getFrameOfReferenceUID(rendering);
},
render: () => {
this.render(ctx);
},
resize: () => {
this.resize(ctx);
},
removeData: () => {
this.removeData(ctx, rendering);
},
};
}
updateDataPresentation(rendering, props) {
applyDataPresentation(rendering, props);
}
applyViewState(ctx, camera) {
applyVolume3DCamera(ctx, camera, {
resetClippingRange: true,
});
}
canvasToWorld(ctx, canvasPos) {
return canvasToWorldContextPool({
canvas: ctx.vtk.canvas,
renderer: ctx.vtk.renderer,
canvasPos,
});
}
worldToCanvas(ctx, worldPos) {
return worldToCanvasContextPool({
canvas: ctx.vtk.canvas,
renderer: ctx.vtk.renderer,
worldPos,
});
}
getFrameOfReferenceUID(rendering) {
return rendering.frameOfReferenceUID;
}
render(ctx) {
ctx.display.requestRender();
}
resize(ctx) {
ctx.display.requestRender();
}
removeData(ctx, rendering) {
rendering.actors.forEach((actorEntry) => {
ctx.vtk.renderer.removeActor(actorEntry.actor);
});
}
}
export class VtkGeometry3DPath {
constructor() {
this.id = 'volume3d:vtk-geometry';
this.type = ViewportType.VOLUME_3D_NEXT;
}
matches(data, options) {
return data.type === 'geometry' && options.renderMode === 'vtkGeometry3d';
}
createRenderPath() {
return new VtkGeometry3DRenderPath();
}
selectContext(rootContext) {
return rootContext;
}
}
function createActorEntries(geometry) {
if (geometry.type === GeometryType.SURFACE) {
const surface = geometry.data;
const polyData = vtkPolyData.newInstance();
polyData.getPoints().setData(surface.points, 3);
polyData.setPolys(vtkCellArray.newInstance({
values: Uint32Array.from(surface.polys),
}));
const mapper = vtkMapper.newInstance();
mapper.setInputData(polyData);
const actor = vtkActor.newInstance();
actor.setMapper(mapper);
actor.setVisibility(surface.visible !== false);
actor
.getProperty()
.setColor(surface.color[0] / 255, surface.color[1] / 255, surface.color[2] / 255);
return [
{
actor,
referencedId: geometry.id,
uid: uuidv4(),
},
];
}
if (geometry.type === GeometryType.MESH) {
const mesh = geometry.data;
return mesh.actors.map((sourceActor, index) => {
return {
actor: sourceActor,
referencedId: geometry.id,
uid: uuidv4(),
};
});
}
throw new Error(`[VolumeViewport3D] Geometry type ${geometry.type} is not supported in 3D Next rendering`);
}
function applyDataPresentation(rendering, props) {
rendering.actors.forEach((actorEntry) => {
const actor = actorEntry.actor;
actor.setVisibility(props?.visible === false ? false : true);
if (props?.opacity !== undefined) {
actor.getProperty().setOpacity(props.opacity);
}
if (props?.color) {
actor
.getProperty()
.setColor(props.color[0] / 255, props.color[1] / 255, props.color[2] / 255);
}
});
}
function hasVisibleProps(ctx) {
const renderer = ctx.vtk.renderer;
return Boolean(renderer.getActors?.().length || renderer.getVolumes?.().length);
}