@kitware/vtk.js
Version:
Visualization Toolkit for the Web
202 lines (183 loc) • 6.79 kB
JavaScript
import { m as macro } from '../../macros2.js';
import vtkAbstractImageMapper from './AbstractImageMapper.js';
import vtkBoundingBox from '../../Common/DataModel/BoundingBox.js';
import vtkImageMapper from './ImageMapper.js';
import { I as createUninitializedBounds } from '../../Common/Core/Math/index.js';
import { intersectWithLineForPointPicking, intersectWithLineForCellPicking } from './AbstractImageMapper/helper.js';
import CoincidentTopologyHelper from './Mapper/CoincidentTopologyHelper.js';
const {
staticOffsetAPI,
otherStaticMethods
} = CoincidentTopologyHelper;
const {
vtkErrorMacro,
vtkWarningMacro
} = macro;
const {
SlicingMode
} = vtkImageMapper;
// ----------------------------------------------------------------------------
// vtkImageArrayMapper methods
// ----------------------------------------------------------------------------
function vtkImageArrayMapper(publicAPI, model) {
// Set our className
model.classHierarchy.push('vtkImageArrayMapper');
//------------------
// Private functions
const _computeSliceToSubSliceMap = () => {
const inputCollection = publicAPI.getInputData();
if (!inputCollection || inputCollection.empty()) {
// clear the map
if (model.sliceToSubSliceMap.length !== 0) {
model.sliceToSubSliceMap.length = 0;
publicAPI.modified();
}
return;
}
if (model.sliceToSubSliceMap.length === 0 || inputCollection.getMTime() > publicAPI.getMTime()) {
const perImageMap = inputCollection.map((image, index) => {
const dim = image.getDimensions();
const out = new Array(dim[model.slicingMode]);
for (let i = 0; i < out.length; ++i) {
out[i] = {
imageIndex: index,
subSlice: i
};
}
return out;
});
model.sliceToSubSliceMap = perImageMap.flat();
publicAPI.modified();
}
};
const _superSetInputData = publicAPI.setInputData;
const _superSetInputConnection = publicAPI.setInputConnection;
//------------------
// Public functions
publicAPI.setInputData = inputData => {
_superSetInputData(inputData);
_computeSliceToSubSliceMap();
};
publicAPI.setInputConnection = (outputPort, port = 0) => {
_superSetInputConnection(outputPort, port);
_computeSliceToSubSliceMap();
};
publicAPI.getImage = (slice = publicAPI.getSlice()) => {
const inputCollection = publicAPI.getInputData();
if (!inputCollection) {
vtkWarningMacro('No input set.');
} else if (slice < 0 || slice >= publicAPI.getTotalSlices()) {
vtkWarningMacro('Invalid slice number.');
} else {
_computeSliceToSubSliceMap();
return inputCollection.getItem(model.sliceToSubSliceMap[slice].imageIndex);
}
return null;
};
// reimplemented from AbstractMapper3D
publicAPI.computeBounds = () => {
const image = publicAPI.getCurrentImage();
if (!image) {
vtkBoundingBox.reset(model.bounds);
return;
}
if (!model.useCustomExtents) {
vtkBoundingBox.setBounds(model.bounds, image.getBounds());
return;
}
const ex = model.customDisplayExtent.slice();
// use sub-slice of the current image,
// which is the k-coordinate.
const nSlice = publicAPI.getSubSlice();
ex[4] = nSlice;
ex[5] = nSlice;
vtkBoundingBox.setBounds(model.bounds, image.extentToBounds(ex));
};
publicAPI.getBoundsForSlice = (slice = publicAPI.getSlice(), halfThickness = 0) => {
const image = publicAPI.getImage(slice);
if (!image) {
return createUninitializedBounds();
}
const extent = image.getSpatialExtent();
const nSlice = publicAPI.getSubSlice(slice);
extent[4] = nSlice - halfThickness;
extent[5] = nSlice + halfThickness;
return image.extentToBounds(extent);
};
publicAPI.getClosestIJKAxis = () => ({
ijkMode: model.slicingMode,
flip: false
});
publicAPI.computeTotalSlices = () => {
const inputCollection = publicAPI.getInputData();
const collectionLength = inputCollection.getNumberOfItems();
let slicesCount = 0;
for (let i = 0; i < collectionLength; ++i) {
const image = inputCollection.getItem(i);
if (image) {
slicesCount += image.getDimensions()[model.slicingMode];
}
}
return slicesCount;
};
publicAPI.getTotalSlices = () => {
_computeSliceToSubSliceMap();
return model.sliceToSubSliceMap.length;
};
// set slice number in terms of imageIndex and subSlice number.
publicAPI.setSlice = slice => {
const inputCollection = publicAPI.getInputData();
if (!inputCollection) {
// No input is set
vtkWarningMacro('No input set.');
return;
}
const totalSlices = publicAPI.getTotalSlices();
if (slice >= 0 && slice < totalSlices) {
model.slice = slice;
publicAPI.modified();
} else {
vtkErrorMacro(`Slice number out of range. Acceptable range is: [0, ${totalSlices > 0 ? totalSlices - 1 : 0}]slice <= totalSlices`);
}
};
publicAPI.computeSlice = (imageIndex, subSlice) => {
_computeSliceToSubSliceMap();
return model.sliceToSubSliceMap.findIndex(x => x.imageIndex === imageIndex && x.subSlice === subSlice);
};
publicAPI.getImageIndex = (slice = publicAPI.getSlice()) => {
_computeSliceToSubSliceMap();
return model.sliceToSubSliceMap[slice]?.imageIndex;
};
publicAPI.getSubSlice = (slice = publicAPI.getSlice()) => {
_computeSliceToSubSliceMap();
return model.sliceToSubSliceMap[slice]?.subSlice;
};
publicAPI.getCurrentImage = () => publicAPI.getImage(publicAPI.getSlice());
publicAPI.intersectWithLineForPointPicking = (p1, p2) => intersectWithLineForPointPicking(p1, p2, publicAPI);
publicAPI.intersectWithLineForCellPicking = (p1, p2) => intersectWithLineForCellPicking(p1, p2, publicAPI);
}
// ----------------------------------------------------------------------------
const DEFAULT_VALUES = {
slicingMode: SlicingMode.K,
sliceToSubSliceMap: []
};
function extend(publicAPI, model, initialValues = {}) {
Object.assign(model, DEFAULT_VALUES, initialValues);
// Build VTK API
vtkAbstractImageMapper.extend(publicAPI, model, initialValues);
// Build VTK API
macro.get(publicAPI, model, ['slicingMode']);
CoincidentTopologyHelper.implementCoincidentTopologyMethods(publicAPI, model);
// Object methods
vtkImageArrayMapper(publicAPI, model);
}
// ----------------------------------------------------------------------------
const newInstance = macro.newInstance(extend, 'vtkImageArrayMapper');
// ----------------------------------------------------------------------------
var index = {
newInstance,
extend,
...staticOffsetAPI,
...otherStaticMethods
};
export { index as default, extend, newInstance };