Skip to content

Instantly share code, notes, and snippets.

@ezesiza
Last active February 1, 2023 23:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ezesiza/0de634cf70106ecd25cae4a604789ae2 to your computer and use it in GitHub Desktop.
Save ezesiza/0de634cf70106ecd25cae4a604789ae2 to your computer and use it in GitHub Desktop.
Implementing CellPicker functionality in Paraview Glance
import vtk2DView from '@kitware/vtk.js/Proxy/Core/View2DProxy';
// import vtkGeometryRepresentationProxy from '@kitware/vtk.js/Proxy/Representations/GeometryRepresentationProxy';
import vtkSkyboxRepresentationProxy from '@kitware/vtk.js/Proxy/Representations/SkyboxRepresentationProxy';
import vtkGlyphRepresentationProxy from '@kitware/vtk.js/Proxy/Representations/GlyphRepresentationProxy';
import vtkLookupTableProxy from '@kitware/vtk.js/Proxy/Core/LookupTableProxy';
import vtkMoleculeRepresentationProxy from '@kitware/vtk.js/Proxy/Representations/MoleculeRepresentationProxy';
import vtkPiecewiseFunctionProxy from '@kitware/vtk.js/Proxy/Core/PiecewiseFunctionProxy';
import vtkProxySource from '@kitware/vtk.js/Proxy/Core/SourceProxy';
import vtkCropWidget from 'paraview-glance/src/vtk/CropWidget';
import vtkAngleWidget from 'paraview-glance/src/vtk/AngleWidget';
import vtkDistance2DWidget from 'paraview-glance/src/vtk/Distance2DWidget';
import vtkTextWidget from 'paraview-glance/src/vtk/TextWidget';
import vtkPaintWidget from '@kitware/vtk.js/Widgets/Widgets3D/PaintWidget';
import vtkScalarBarGeometryRepresentationProxy from 'paraview-glance/src/vtk/ScalarBarActor';
import vtkCustomSliceRepresentationProxy from 'paraview-glance/src/vtk/CustomSliceRepresentationProxy';
import vtkCustomVolumeRepresentationProxy from 'paraview-glance/src/vtk/CustomVolumeRepresentationProxy';
import vtkLabelMapVolumeRepProxy from 'paraview-glance/src/vtk/LabelMapVolumeRepProxy';
import vtkLabelMapSliceRepProxy from 'paraview-glance/src/vtk/LabelMapSliceRepProxy';
import vtkWidgetProxy from 'paraview-glance/src/vtk/WidgetProxy';
import vtkAnimationProxyManager from '@kitware/vtk.js/Proxy/Animation/AnimationProxyManager';
import vtkTimeStepBasedAnimationProxy from '@kitware/vtk.js/Proxy/Animation/TimeStepBasedAnimationHandlerProxy';
import ConfigUtils from 'paraview-glance/src/config/configUtils';
import proxyUI from 'paraview-glance/src/config/proxyUI';
import proxyLinks from 'paraview-glance/src/config/proxyLinks';
import proxyViewRepresentationMapping from 'paraview-glance/src/config/proxyViewRepresentationMapping';
import vtkCellPickerViewRepresentationProxy from '../vtk/CellPicker';
const { createProxyDefinition, activateOnCreate } = ConfigUtils;
const ViewToWidgetTypes = {
View3D: 'VOLUME',
View2D_X: 'SLICE',
View2D_Y: 'SLICE',
View2D_Z: 'SLICE',
};
function createDefaultView(classFactory, ui, options, props) {
return activateOnCreate(
createProxyDefinition(
classFactory,
ui,
[
{
type: 'application',
link: 'AnnotationOpacity',
property: 'annotationOpacity',
updateOnBind: true,
},
{
type: 'application',
link: 'OrientationAxesVisibility',
property: 'orientationAxesVisibility',
updateOnBind: true,
},
{
type: 'application',
link: 'OrientationAxesPreset',
property: 'presetToOrientationAxes',
updateOnBind: true,
},
{
type: 'application',
link: 'OrientationAxesType',
property: 'orientationAxesType',
updateOnBind: true,
},
],
options,
props
)
);
}
// ----------------------------------------------------------------------------
export default {
definitions: {
Proxy: {
LookupTable: createProxyDefinition(vtkLookupTableProxy, [], [], {
presetName: 'Default (Cool to Warm)',
}),
PiecewiseFunction: createProxyDefinition(vtkPiecewiseFunctionProxy),
},
Widgets: {
Crop: createProxyDefinition(vtkWidgetProxy, [], [], {
factory: vtkCropWidget,
viewTypes: ViewToWidgetTypes,
}),
Paint: createProxyDefinition(vtkWidgetProxy, [], [], {
factory: vtkPaintWidget,
viewTypes: ViewToWidgetTypes,
}),
Angle: createProxyDefinition(vtkWidgetProxy, [], [], {
factory: vtkAngleWidget,
viewTypes: ViewToWidgetTypes,
}),
Ruler: createProxyDefinition(vtkWidgetProxy, [], [], {
factory: vtkDistance2DWidget,
viewTypes: ViewToWidgetTypes,
}),
Text: createProxyDefinition(vtkWidgetProxy, [], [], {
factory: vtkTextWidget,
viewTypes: ViewToWidgetTypes,
}),
},
Sources: {
TrivialProducer: activateOnCreate(createProxyDefinition(vtkProxySource)),
// differentiate LabelMaps
LabelMap: createProxyDefinition(vtkProxySource),
},
Representations: {
Geometry: createProxyDefinition(vtkScalarBarGeometryRepresentationProxy, proxyUI.Geometry, proxyLinks.Geometry),
Skybox: createProxyDefinition(vtkSkyboxRepresentationProxy, proxyUI.Skybox, proxyLinks.Skybox),
Slice: createProxyDefinition(vtkCustomSliceRepresentationProxy, proxyUI.Slice, proxyLinks.Slice),
SliceX: createProxyDefinition(
vtkCustomSliceRepresentationProxy,
proxyUI.Slice,
[
{
link: 'SliceX',
property: 'slice',
updateOnBind: true,
type: 'application',
},
].concat(proxyLinks.Slice)
),
SliceY: createProxyDefinition(
vtkCustomSliceRepresentationProxy,
proxyUI.Slice,
[
{
link: 'SliceY',
property: 'slice',
updateOnBind: true,
type: 'application',
},
].concat(proxyLinks.Slice)
),
SliceZ: createProxyDefinition(
vtkCustomSliceRepresentationProxy,
proxyUI.Slice,
[
{
link: 'SliceZ',
property: 'slice',
updateOnBind: true,
type: 'application',
},
].concat(proxyLinks.Slice)
),
Volume: createProxyDefinition(vtkCustomVolumeRepresentationProxy, proxyUI.Volume, proxyLinks.Volume),
Molecule: createProxyDefinition(vtkMoleculeRepresentationProxy, proxyUI.Molecule, proxyLinks.Molecule),
Glyph: createProxyDefinition(vtkGlyphRepresentationProxy, proxyUI.Glyph, proxyLinks.Glyph),
LabelMapVolume: createProxyDefinition(
vtkLabelMapVolumeRepProxy,
[], // ui
[] // links
),
LabelMapSlice: createProxyDefinition(vtkLabelMapSliceRepProxy),
LabelMapSliceX: createProxyDefinition(
vtkLabelMapSliceRepProxy,
[], // ui
[
{
link: 'SliceX',
property: 'slice',
updateOnBind: true,
type: 'application',
},
] // links
),
LabelMapSliceY: createProxyDefinition(
vtkLabelMapSliceRepProxy,
[], // ui
[
{
link: 'SliceY',
property: 'slice',
updateOnBind: true,
type: 'application',
},
] // links
),
LabelMapSliceZ: createProxyDefinition(
vtkLabelMapSliceRepProxy,
[], // ui
[
{
link: 'SliceZ',
property: 'slice',
updateOnBind: true,
type: 'application',
},
] // links
),
},
Views: {
View3D: createDefaultView(vtkCellPickerViewRepresentationProxy, proxyUI.View3D),
View2D: createDefaultView(vtk2DView, proxyUI.View2D),
View2D_X: createDefaultView(vtk2DView, proxyUI.View2D, { axis: 0 }),
View2D_Y: createDefaultView(vtk2DView, proxyUI.View2D, { axis: 1 }),
View2D_Z: createDefaultView(vtk2DView, proxyUI.View2D, { axis: 2 }),
},
AnimationManager: {
AnimationProxyManager: {
class: vtkAnimationProxyManager,
},
},
Animations: {
TimeStepAnimation: {
class: vtkTimeStepBasedAnimationProxy,
},
},
},
representations: {
View3D: proxyViewRepresentationMapping.View3D,
View2D: proxyViewRepresentationMapping.View2D,
View2D_X: {
...proxyViewRepresentationMapping.View2D,
vtkImageData: { name: 'SliceX' },
vtkLabelMap: { name: 'LabelMapSliceX' },
},
View2D_Y: {
...proxyViewRepresentationMapping.View2D,
vtkImageData: { name: 'SliceY' },
vtkLabelMap: { name: 'LabelMapSliceY' },
},
View2D_Z: {
...proxyViewRepresentationMapping.View2D,
vtkImageData: { name: 'SliceZ' },
vtkLabelMap: { name: 'LabelMapSliceZ' },
},
},
filters: {
vtkPolyData: [],
vtkImageData: [],
vtkMolecule: [],
Glyph: [],
},
};
import '@kitware/vtk.js/Rendering/Profiles/Geometry';
import macro from '@kitware/vtk.js/macros';
import vtkMapper from '@kitware/vtk.js/Rendering/Core/Mapper';
import vtkViewProxy from '@kitware/vtk.js/Proxy/Core/ViewProxy';
import vtkSphereSource from '@kitware/vtk.js/Filters/Sources/SphereSource';
import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor';
import vtkCellPicker from '@kitware/vtk.js/Rendering/Core/CellPicker';
function vtkCellPickerViewRepresentationProxy(publicAPI, model) {
model.classHierarchy.push('vtkCellPickerViewRepresentationProxy');
// Only try to pick model image
const actor = vtkActor.newInstance();
const mapper = vtkMapper.newInstance();
actor.setMapper(mapper);
const picker = vtkCellPicker.newInstance();
picker.setPickFromList(1);
picker.setTolerance(0);
picker.initializePickList();
picker.addPickList(actor);
model.renderWindow.getInteractor().onRightButtonPress((callData) => {
if (model.renderer !== callData.pokedRenderer) {
return;
}
console.log(model);
const pos = callData.position;
const point = [pos.x, pos.y, 0.0];
picker.pick(point, model.renderer);
if (picker.getActors().length === 0) {
const pickedPoint = picker.getPickPosition();
const sphere = vtkSphereSource.newInstance();
sphere.setCenter(pickedPoint);
sphere.setRadius(0.01);
console.log(sphere.getRadius());
const sphereMapper = vtkMapper.newInstance();
sphereMapper.setInputData(sphere.getOutputData());
const sphereActor = vtkActor.newInstance();
sphereActor.setMapper(sphereMapper);
sphereActor.getProperty().setColor(1.0, 0.0, 0.0);
model.renderer.addActor(sphereActor);
} else {
// const pickedCellId = picker.getCellId();
const pickedPoints = picker.getPickedPositions();
console.log(pickedPoints);
for (let i = 0; i < pickedPoints.length; i++) {
const pickedPoint = pickedPoints[i];
const sphere = vtkSphereSource.newInstance();
sphere.setCenter(pickedPoint);
sphere.setRadius(0.01);
const sphereMapper = vtkMapper.newInstance();
sphereMapper.setInputData(sphere.getOutputData());
const sphereActor = vtkActor.newInstance();
sphereActor.setMapper(sphereMapper);
sphereActor.getProperty().setColor(0.0, 1.0, 0.0);
model.renderer.addActor(sphereActor);
}
}
model.renderWindow.render();
});
}
const DEFAULT_VALUES = {};
export function extend(publicAPI, model, initialValues = {}) {
Object.assign(model, DEFAULT_VALUES, initialValues);
vtkViewProxy.extend(publicAPI, model);
macro.setGet(publicAPI, model, []);
vtkCellPickerViewRepresentationProxy(publicAPI, model);
}
export const newInstance = macro.newInstance(extend, 'vtkCellPickerViewRepresentationProxy');
export default { newInstance, extend };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment