import { vec4, mat4 } from 'gl-matrix';
import macro, { vtkWarningMacro } from 'vtk.js/Sources/macros'; import vtkDataArray from 'vtk.js/Sources/Common/Core/DataArray'; import vtkMath from 'vtk.js/Sources/Common/Core/Math'; import vtkMatrixBuilder from 'vtk.js/Sources/Common/Core/MatrixBuilder'; import { VtkDataTypes } from 'vtk.js/Sources/Common/Core/DataArray/Constants'; import vtkBoundingBox from 'vtk.js/Sources/Common/DataModel/BoundingBox'; import vtkImageData from 'vtk.js/Sources/Common/DataModel/ImageData'; import vtkImageInterpolator from 'vtk.js/Sources/Imaging/Core/ImageInterpolator'; import vtkImagePointDataIterator from 'vtk.js/Sources/Imaging/Core/ImagePointDataIterator'; import { ImageBorderMode, InterpolationMode, } from 'vtk.js/Sources/Imaging/Core/AbstractImageInterpolator/Constants'; import { vtkInterpolationMathFloor, vtkInterpolationMathRound, vtkInterpolationMathClamp, } from 'vtk.js/Sources/Imaging/Core/AbstractImageInterpolator/InterpolationInfo'; import Constants from 'vtk.js/Sources/Imaging/Core/ImageReslice/Constants';
const { SlabMode } = Constants;
const { vtkErrorMacro } = macro;
function vtkImageReslice(publicAPI, model) { model.classHierarchy.push('vtkImageReslice'); const superClass = { ...publicAPI };
const indexMatrix = mat4.identity(new Float64Array(16)); let optimizedTransform = null;
function getImageResliceSlabTrap(tmpPtr, inComponents, sampleCount, f) { const n = sampleCount - 1; for (let i = 0; i < inComponents; i += 1) { let result = tmpPtr[i] * 0.5; for (let j = 1; j < n; j += 1) { result += tmpPtr[i + j * inComponents]; } result += tmpPtr[i + n * inComponents] * 0.5; tmpPtr[i] = result * f; } }
function getImageResliceSlabSum(tmpPtr, inComponents, sampleCount, f) { for (let i = 0; i < inComponents; i += 1) { let result = tmpPtr[i]; for (let j = 1; j < sampleCount; j += 1) { result += tmpPtr[i + j * inComponents]; } tmpPtr[i] = result * f; } }
function getImageResliceCompositeMinValue(tmpPtr, inComponents, sampleCount) { for (let i = 0; i < inComponents; i += 1) { let result = tmpPtr[i]; for (let j = 1; j < sampleCount; j += 1) { result = Math.min(result, tmpPtr[i + j * inComponents]); } tmpPtr[i] = result; } }
function getImageResliceCompositeMaxValue(tmpPtr, inComponents, sampleCount) { for (let i = 0; i < inComponents; i += 1) { let result = tmpPtr[i]; for (let j = 1; j < sampleCount; j += 1) { result = Math.max(result, tmpPtr[i + j * inComponents]); } tmpPtr[i] = result; } }
function getImageResliceCompositeMeanValue( tmpPtr, inComponents, sampleCount ) { const f = 1.0 / sampleCount; getImageResliceSlabSum(tmpPtr, inComponents, sampleCount, f); }
function getImageResliceCompositeMeanTrap(tmpPtr, inComponents, sampleCount) { const f = 1.0 / (sampleCount - 1); getImageResliceSlabTrap(tmpPtr, inComponents, sampleCount, f); }
function getImageResliceCompositeSumValue(tmpPtr, inComponents, sampleCount) { const f = 1.0; getImageResliceSlabSum(tmpPtr, inComponents, sampleCount, f); }
function getImageResliceCompositeSumTrap(tmpPtr, inComponents, sampleCount) { const f = 1.0; getImageResliceSlabTrap(tmpPtr, inComponents, sampleCount, f); }
publicAPI.getMTime = () => { let mTime = superClass.getMTime(); if (model.resliceTransform) { mTime = Math.max(mTime, model.resliceTransform.getMTime()); } return mTime; };
publicAPI.setResliceAxes = (resliceAxes) => { if (!model.resliceAxes) { model.resliceAxes = mat4.identity(new Float64Array(16)); }
if (!mat4.exactEquals(model.resliceAxes, resliceAxes)) { mat4.copy(model.resliceAxes, resliceAxes);
publicAPI.modified(); return true; } return false; };
publicAPI.requestData = (inData, outData) => { const input = inData[0];
if (!input) { vtkErrorMacro('Invalid or missing input'); return; }
const origin = input.getOrigin(); const inSpacing = input.getSpacing(); const dims = input.getDimensions(); const inScalars = input.getPointData().getScalars(); const inWholeExt = [0, dims[0] - 1, 0, dims[1] - 1, 0, dims[2] - 1];
const outOrigin = [0, 0, 0]; const outSpacing = [1, 1, 1]; const outWholeExt = [0, 0, 0, 0, 0, 0]; const outDims = [0, 0, 0];
const matrix = mat4.identity(new Float64Array(16)); if (model.resliceAxes) { mat4.multiply(matrix, matrix, model.resliceAxes); } const imatrix = new Float64Array(16); mat4.invert(imatrix, matrix);
const inCenter = [ origin[0] + 0.5 * (inWholeExt[0] + inWholeExt[1]) * inSpacing[0], origin[1] + 0.5 * (inWholeExt[2] + inWholeExt[3]) * inSpacing[1], origin[2] + 0.5 * (inWholeExt[4] + inWholeExt[5]) * inSpacing[2], ];
let maxBounds = null; if (model.autoCropOutput) { maxBounds = publicAPI.getAutoCroppedOutputBounds(input); }
for (let i = 0; i < 3; i++) { let s = 0; let d = 0; let e = 0; let c = 0;
if (model.transformInputSampling) { let r = 0.0; for (let j = 0; j < 3; j++) { c += imatrix[4 * j + i] * (inCenter[j] - matrix[4 * 3 + j]); const tmp = matrix[4 * i + j] * matrix[4 * i + j]; s += tmp * Math.abs(inSpacing[j]); d += tmp * (inWholeExt[2 * j + 1] - inWholeExt[2 * j]) * Math.abs(inSpacing[j]); e += tmp * inWholeExt[2 * j]; r += tmp; } s /= r; d /= r * Math.sqrt(r); e /= r; } else { c = inCenter[i]; s = inSpacing[i]; d = (inWholeExt[2 * i + 1] - inWholeExt[2 * i]) * s; e = inWholeExt[2 * i]; }
if (model.outputSpacing == null) { outSpacing[i] = s; } else { outSpacing[i] = model.outputSpacing[i]; }
if (i >= model.outputDimensionality) { outWholeExt[2 * i] = 0; outWholeExt[2 * i + 1] = 0; } else if (model.outputExtent == null) { if (model.autoCropOutput) { d = maxBounds[2 * i + 1] - maxBounds[2 * i]; } outWholeExt[2 * i] = Math.round(e); outWholeExt[2 * i + 1] = Math.round( outWholeExt[2 * i] + Math.abs(d / outSpacing[i]) ); } else { outWholeExt[2 * i] = model.outputExtent[2 * i]; outWholeExt[2 * i + 1] = model.outputExtent[2 * i + 1]; }
if (i >= model.outputDimensionality) { outOrigin[i] = 0; } else if (model.outputOrigin == null) { if (model.autoCropOutput) { outOrigin[i] = maxBounds[2 * i] - outWholeExt[2 * i] * outSpacing[i]; } else { outOrigin[i] = c - 0.5 * (outWholeExt[2 * i] + outWholeExt[2 * i + 1]) * outSpacing[i]; } } else { outOrigin[i] = model.outputOrigin[i]; } outDims[i] = outWholeExt[2 * i + 1] - outWholeExt[2 * i] + 1; }
let dataType = inScalars.getDataType(); if (model.outputScalarType) { dataType = model.outputScalarType; }
const numComponents = input .getPointData() .getScalars() .getNumberOfComponents();
const outScalarsData = macro.newTypedArray( dataType, outDims[0] * outDims[1] * outDims[2] * numComponents ); const outScalars = vtkDataArray.newInstance({ name: 'Scalars', values: outScalarsData, numberOfComponents: numComponents, });
const output = vtkImageData.newInstance(); output.setDimensions(outDims); output.setOrigin(outOrigin); output.setSpacing(outSpacing); if (model.outputDirection) { output.setDirection(model.outputDirection); } output.getPointData().setScalars(outScalars);
publicAPI.getIndexMatrix(input, output);
let interpolationMode = model.interpolationMode; model.usePermuteExecute = false; if (model.optimization) { if ( optimizedTransform == null && model.slabSliceSpacingFraction === 1.0 && model.interpolator.isSeparable() && publicAPI.isPermutationMatrix(indexMatrix) ) { model.usePermuteExecute = true; if (publicAPI.canUseNearestNeighbor(indexMatrix, outWholeExt)) { interpolationMode = InterpolationMode.NEAREST; } } } model.interpolator.setInterpolationMode(interpolationMode);
let borderMode = ImageBorderMode.CLAMP; borderMode = model.wrap ? ImageBorderMode.REPEAT : borderMode; borderMode = model.mirror ? ImageBorderMode.MIRROR : borderMode; model.interpolator.setBorderMode(borderMode);
const mintol = 7.62939453125e-6; const maxtol = 2.0 * 2147483647; let tol = 0.5 * model.border; tol = borderMode === ImageBorderMode.CLAMP ? tol : maxtol; tol = tol > mintol ? tol : mintol; model.interpolator.setTolerance(tol);
model.interpolator.initialize(input);
publicAPI.vtkImageResliceExecute(input, output);
model.interpolator.releaseData();
outData[0] = output;
};
publicAPI.vtkImageResliceExecute = (input, output) => { const inScalars = input.getPointData().getScalars(); const outScalars = output.getPointData().getScalars(); let outPtr = outScalars.getData(); const outExt = output.getExtent(); const newmat = indexMatrix; const outputStencil = null;
const nsamples = Math.max(model.slabNumberOfSlices, 1);
const slabSampleSpacing = model.slabSliceSpacingFraction;
const perspective = publicAPI.isPerspectiveMatrix(newmat);
let inPtr = inScalars.getData(); const inputScalarSize = 1; const inputScalarType = inScalars.getDataType(); const inComponents = inScalars.getNumberOfComponents(); const componentOffset = model.interpolator.getComponentOffset(); const borderMode = model.interpolator.getBorderMode(); const inDims = input.getDimensions(); const inExt = [0, inDims[0] - 1, 0, inDims[1] - 1, 0, inDims[2] - 1]; const inInc = [0, 0, 0]; inInc[0] = inScalars.getNumberOfComponents(); inInc[1] = inInc[0] * inDims[0]; inInc[2] = inInc[1] * inDims[1];
const fullSize = inDims[0] * inDims[1] * inDims[2]; if (componentOffset > 0 && componentOffset + inComponents < inInc[0]) { inPtr = inPtr.subarray(inputScalarSize * componentOffset); }
let interpolationMode = InterpolationMode.NEAREST; if (model.interpolator.isA('vtkImageInterpolator')) { interpolationMode = model.interpolator.getInterpolationMode(); }
const convertScalars = null; const rescaleScalars = model.scalarShift !== 0.0 || model.scalarScale !== 1.0;
const optimizeNearest = interpolationMode === InterpolationMode.NEAREST && borderMode === ImageBorderMode.CLAMP && !( optimizedTransform != null || perspective || convertScalars != null || rescaleScalars ) && inputScalarType === outScalars.getDataType() && fullSize === inScalars.getNumberOfTuples() && model.border === true && nsamples <= 1;
const scalarType = outScalars.getDataType(); const scalarSize = 1; const outComponents = outScalars.getNumberOfComponents();
const xAxis = [0, 0, 0, 0]; const yAxis = [0, 0, 0, 0]; const zAxis = [0, 0, 0, 0]; const origin = [0, 0, 0, 0]; for (let i = 0; i < 4; ++i) { xAxis[i] = newmat[4 * 0 + i]; yAxis[i] = newmat[4 * 1 + i]; zAxis[i] = newmat[4 * 2 + i]; origin[i] = newmat[4 * 3 + i]; }
let floatPtr = null; if (!optimizeNearest) { floatPtr = new Float64Array( inComponents * (outExt[1] - outExt[0] + nsamples) ); }
const background = macro.newTypedArray( inputScalarType, model.backgroundColor );
const forceClamping = interpolationMode > InterpolationMode.LINEAR || (nsamples > 1 && model.slabMode === SlabMode.SUM); const convertpixels = publicAPI.getConversionFunc( inputScalarType, scalarType, model.scalarShift, model.scalarScale, forceClamping ); const setpixels = publicAPI.getSetPixelsFunc( scalarType, scalarSize, outComponents, outPtr ); const composite = publicAPI.getCompositeFunc( model.slabMode, model.slabTrapezoidIntegration );
let idY = outExt[2] - 1; let idZ = outExt[4] - 1; const inPoint0 = [0.0, 0.0, 0.0, 0.0]; const inPoint1 = [0.0, 0.0, 0.0, 0.0];
const iter = vtkImagePointDataIterator.newInstance(); iter.initialize(output, outExt, model.stencil, null); const outPtr0 = iter.getScalars(output, 0); let outPtrIndex = 0; const outTmp = macro.newTypedArray( scalarType, vtkBoundingBox.getDiagonalLength(outExt) * outComponents * 2 );
const interpolatedPtr = new Float64Array(inComponents * nsamples); const interpolatedPoint = new Float64Array(inComponents);
for (; !iter.isAtEnd(); iter.nextSpan()) { const span = iter.spanEndId() - iter.getId(); outPtrIndex = iter.getId() * scalarSize * outComponents;
if (!iter.isInStencil()) { const n = setpixels(outTmp, background, outComponents, span); for (let i = 0; i < n; ++i) { outPtr0[outPtrIndex++] = outTmp[i]; } } else { const outIndex = iter.getIndex();
if (outIndex[2] > idZ) { idZ = outIndex[2]; inPoint0[0] = origin[0] + idZ * zAxis[0]; inPoint0[1] = origin[1] + idZ * zAxis[1]; inPoint0[2] = origin[2] + idZ * zAxis[2]; inPoint0[3] = origin[3] + idZ * zAxis[3]; idY = outExt[2] - 1; }
if (outIndex[1] > idY) { idY = outIndex[1]; inPoint1[0] = inPoint0[0] + idY * yAxis[0]; inPoint1[1] = inPoint0[1] + idY * yAxis[1]; inPoint1[2] = inPoint0[2] + idY * yAxis[2]; inPoint1[3] = inPoint0[3] + idY * yAxis[3]; }
const idXmin = outIndex[0]; const idXmax = idXmin + span - 1;
if (!optimizeNearest) { let wasInBounds = 1; let isInBounds = 1; let startIdX = idXmin; let idX = idXmin; const tmpPtr = floatPtr; let pixelIndex = 0;
while (startIdX <= idXmax) { for (; idX <= idXmax && isInBounds === wasInBounds; idX++) { const inPoint2 = [ inPoint1[0] + idX * xAxis[0], inPoint1[1] + idX * xAxis[1], inPoint1[2] + idX * xAxis[2], inPoint1[3] + idX * xAxis[3], ];
const inPoint3 = [0, 0, 0, 0]; let inPoint = inPoint2; isInBounds = false;
let interpolatedPtrIndex = 0; for (let sample = 0; sample < nsamples; ++sample) { if (nsamples > 1) { let s = sample - 0.5 * (nsamples - 1); s *= slabSampleSpacing; inPoint3[0] = inPoint2[0] + s * zAxis[0]; inPoint3[1] = inPoint2[1] + s * zAxis[1]; inPoint3[2] = inPoint2[2] + s * zAxis[2]; inPoint3[3] = inPoint2[3] + s * zAxis[3]; inPoint = inPoint3; }
if (perspective) { const f = 1 / inPoint[3]; inPoint[0] *= f; inPoint[1] *= f; inPoint[2] *= f; }
if (optimizedTransform !== null) { const inOrigin = model.interpolator.getOrigin(); const inSpacing = model.interpolator.getSpacing(); const inInvSpacing = [ 1.0 / inSpacing[0], 1.0 / inSpacing[1], 1.0 / inSpacing[2], ];
publicAPI.applyTransform( optimizedTransform, inPoint, inOrigin, inInvSpacing ); }
if (model.interpolator.checkBoundsIJK(inPoint)) { isInBounds = 1; model.interpolator.interpolateIJK(inPoint, interpolatedPoint); for (let i = 0; i < inComponents; ++i) { interpolatedPtr[interpolatedPtrIndex++] = interpolatedPoint[i]; } } }
if (interpolatedPtrIndex > inComponents) { composite( interpolatedPtr, inComponents, interpolatedPtrIndex / inComponents ); } for (let i = 0; i < inComponents; ++i) { tmpPtr[pixelIndex++] = interpolatedPtr[i]; }
wasInBounds = idX > idXmin ? wasInBounds : isInBounds; }
const endIdX = idX - 1 - (isInBounds !== wasInBounds); const numpixels = endIdX - startIdX + 1;
let n = 0; if (wasInBounds) { if (outputStencil) { outputStencil.insertNextExtent(startIdX, endIdX, idY, idZ); }
if (rescaleScalars) { publicAPI.rescaleScalars( floatPtr, inComponents, idXmax - idXmin + 1, model.scalarShift, model.scalarScale ); }
if (convertScalars) { convertScalars( floatPtr.subarray(startIdX * inComponents), outTmp, inputScalarType, inComponents, numpixels, startIdX, idY, idZ ); n = numpixels * outComponents * scalarSize; } else { n = convertpixels( outTmp, floatPtr.subarray(startIdX * inComponents), outComponents, numpixels ); } } else { n = setpixels(outTmp, background, outComponents, numpixels); } for (let i = 0; i < n; ++i) { outPtr0[outPtrIndex++] = outTmp[i]; }
startIdX += numpixels; wasInBounds = isInBounds; } } else { const inPtrTmp0 = inPtr; const outPtrTmp = outPtr;
const inIncX = inInc[0] * inputScalarSize; const inIncY = inInc[1] * inputScalarSize; const inIncZ = inInc[2] * inputScalarSize;
const inExtX = inExt[1] - inExt[0] + 1; const inExtY = inExt[3] - inExt[2] + 1; const inExtZ = inExt[5] - inExt[4] + 1;
let startIdX = idXmin; let endIdX = idXmin - 1; let isInBounds = false; const bytesPerPixel = inputScalarSize * inComponents;
for (let iidX = idXmin; iidX <= idXmax; iidX++) { const inPoint = [ inPoint1[0] + iidX * xAxis[0], inPoint1[1] + iidX * xAxis[1], inPoint1[2] + iidX * xAxis[2], ];
const inIdX = vtkInterpolationMathRound(inPoint[0]) - inExt[0]; const inIdY = vtkInterpolationMathRound(inPoint[1]) - inExt[2]; const inIdZ = vtkInterpolationMathRound(inPoint[2]) - inExt[4];
if ( inIdX >= 0 && inIdX < inExtX && inIdY >= 0 && inIdY < inExtY && inIdZ >= 0 && inIdZ < inExtZ ) { if (!isInBounds) { startIdX = iidX; isInBounds = true; const n = setpixels( outTmp, background, outComponents, startIdX - idXmin ); for (let i = 0; i < n; ++i) { outPtr0[outPtrIndex++] = outTmp[i]; } } endIdX = iidX;
let offset = inIdX * inIncX + inIdY * inIncY + inIdZ * inIncZ;
switch (bytesPerPixel) { case 1: outPtr0[outPtrIndex++] = inPtrTmp0[offset]; break; case 2: case 3: case 4: case 8: case 12: case 16: for (let i = 0; i < bytesPerPixel; ++i) { outPtr0[outPtrIndex++] = inPtrTmp0[offset + i]; } break; default: { let oc = 0; do { outPtr0[outPtrIndex++] = inPtrTmp0[offset++]; } while (++oc !== bytesPerPixel); break; } } } else if (isInBounds) { break; } }
outPtr = outPtrTmp; const n = setpixels( outTmp, background, outComponents, idXmax - endIdX ); for (let i = 0; i < n; ++i) { outPtr0[outPtrIndex++] = outTmp[i]; }
if (outputStencil && endIdX >= startIdX) { outputStencil.insertNextExtent(startIdX, endIdX, idY, idZ); } } } } };
publicAPI.getIndexMatrix = (input, output) => { const transform = mat4.identity(new Float64Array(16)); optimizedTransform = null;
if (model.resliceAxes) { mat4.copy(transform, model.resliceAxes); } if (model.resliceTransform) { if (model.resliceTransform.isA('vtkHomogeneousTransform')) { mat4.multiply(transform, model.resliceTransform.getMatrix(), transform); } else { vtkWarningMacro('Non homogeneous transform have not yet been ported'); } }
const outMatrix = output.getIndexToWorld(); mat4.multiply(transform, transform, outMatrix);
if (optimizedTransform == null) { const inMatrix = input.getWorldToIndex(); mat4.multiply(transform, inMatrix, transform); }
mat4.copy(indexMatrix, transform);
return indexMatrix; };
publicAPI.getAutoCroppedOutputBounds = (input) => { const inOrigin = input.getOrigin(); const inSpacing = input.getSpacing(); const inDirection = input.getDirection(); const dims = input.getDimensions(); const inWholeExt = [0, dims[0] - 1, 0, dims[1] - 1, 0, dims[2] - 1];
const matrix = new Float64Array(16); if (model.resliceAxes) { mat4.invert(matrix, model.resliceAxes); } else { mat4.identity(matrix); } let transform = null; if (model.resliceTransform) { transform = model.resliceTransform.getInverse(); } let imageTransform = null; if (!vtkMath.isIdentity3x3(inDirection)) { imageTransform = vtkMatrixBuilder .buildFromRadian() .translate(inOrigin[0], inOrigin[1], inOrigin[2]) .multiply3x3(inDirection) .translate(-inOrigin[0], -inOrigin[1], -inOrigin[2]) .invert() .getMatrix(); }
const bounds = [ Number.MAX_VALUE, -Number.MAX_VALUE, Number.MAX_VALUE, -Number.MAX_VALUE, Number.MAX_VALUE, -Number.MAX_VALUE, ];
const point = [0, 0, 0, 0]; for (let i = 0; i < 8; ++i) { point[0] = inOrigin[0] + inWholeExt[i % 2] * inSpacing[0]; point[1] = inOrigin[1] + inWholeExt[2 + (Math.floor(i / 2) % 2)] * inSpacing[1]; point[2] = inOrigin[2] + inWholeExt[4 + (Math.floor(i / 4) % 2)] * inSpacing[2]; point[3] = 1.0;
if (imageTransform) { vec4.transformMat4(point, point, imageTransform); }
if (model.resliceTransform) { transform.transformPoint(point, point); }
vec4.transformMat4(point, point, matrix);
const f = 1.0 / point[3]; point[0] *= f; point[1] *= f; point[2] *= f;
for (let j = 0; j < 3; ++j) { if (point[j] > bounds[2 * j + 1]) { bounds[2 * j + 1] = point[j]; } if (point[j] < bounds[2 * j]) { bounds[2 * j] = point[j]; } } } return bounds; };
publicAPI.getDataTypeMinMax = (dataType) => { switch (dataType) { case 'Int8Array': return { min: -128, max: 127 }; case 'Int16Array': return { min: -32768, max: 32767 }; case 'Uint16Array': return { min: 0, max: 65535 }; case 'Int32Array': return { min: -2147483648, max: 2147483647 }; case 'Uint32Array': return { min: 0, max: 4294967295 }; case 'Float32Array': return { min: -1.2e38, max: 1.2e38 }; case 'Float64Array': return { min: -1.2e38, max: 1.2e38 }; case 'Uint8Array': case 'Uint8ClampedArray': default: return { min: 0, max: 255 }; } };
publicAPI.clamp = (outPtr, inPtr, numscalars, n, min, max) => { const count = n * numscalars; for (let i = 0; i < count; ++i) { outPtr[i] = vtkInterpolationMathClamp(inPtr[i], min, max); } return count; };
publicAPI.convert = (outPtr, inPtr, numscalars, n) => { const count = n * numscalars; for (let i = 0; i < count; ++i) { outPtr[i] = Math.round(inPtr[i]); } return count; };
publicAPI.getConversionFunc = ( inputType, dataType, scalarShift, scalarScale, forceClamping ) => { let useClamping = forceClamping; if ( dataType !== VtkDataTypes.FLOAT && dataType !== VtkDataTypes.DOUBLE && !forceClamping ) { const inMinMax = publicAPI.getDataTypeMinMax(inputType); let checkMin = (inMinMax.min + scalarShift) * scalarScale; let checkMax = (inMinMax.max + scalarShift) * scalarScale; const outMinMax = publicAPI.getDataTypeMinMax(dataType); const outputMin = outMinMax.min; const outputMax = outMinMax.max; if (checkMin > checkMax) { const tmp = checkMax; checkMax = checkMin; checkMin = tmp; } useClamping = checkMin < outputMin || checkMax > outputMax; }
if ( useClamping && dataType !== VtkDataTypes.FLOAT && dataType !== VtkDataTypes.DOUBLE ) { const minMax = publicAPI.getDataTypeMinMax(dataType); const clamp = (outPtr, inPtr, numscalars, n) => publicAPI.clamp(outPtr, inPtr, numscalars, n, minMax.min, minMax.max); return clamp; } return publicAPI.convert; };
publicAPI.set = (outPtr, inPtr, numscalars, n) => { const count = numscalars * n; for (let i = 0; i < n; ++i) { outPtr[i] = inPtr[i]; } return count; };
publicAPI.set1 = (outPtr, inPtr, numscalars, n) => { outPtr.fill(inPtr[0], 0, n); return n; };
publicAPI.getSetPixelsFunc = (dataType, dataSize, numscalars, dataPtr) => numscalars === 1 ? publicAPI.set1 : publicAPI.set;
publicAPI.getCompositeFunc = (slabMode, slabTrapezoidIntegration) => { let composite = null; switch (slabMode) { case SlabMode.MIN: composite = getImageResliceCompositeMinValue; break; case SlabMode.MAX: composite = getImageResliceCompositeMaxValue; break; case SlabMode.MEAN: if (slabTrapezoidIntegration) { composite = getImageResliceCompositeMeanTrap; } else { composite = getImageResliceCompositeMeanValue; } break; case SlabMode.SUM: if (slabTrapezoidIntegration) { composite = getImageResliceCompositeSumTrap; } else { composite = getImageResliceCompositeSumValue; } break; }
return composite; };
publicAPI.applyTransform = (newTrans, inPoint, inOrigin, inInvSpacing) => { inPoint[3] = 1; vec4.transformMat4(inPoint, inPoint, newTrans); inPoint[0] -= inOrigin[0]; inPoint[1] -= inOrigin[1]; inPoint[2] -= inOrigin[2]; inPoint[0] *= inInvSpacing[0]; inPoint[1] *= inInvSpacing[1]; inPoint[2] *= inInvSpacing[2]; };
publicAPI.rescaleScalars = ( floatData, components, n, scalarShift, scalarScale ) => { const m = n * components; for (let i = 0; i < m; ++i) { floatData[i] = (floatData[i] + scalarShift) * scalarScale; } };
publicAPI.isPermutationMatrix = (matrix) => { for (let i = 0; i < 3; i++) { if (matrix[4 * i + 3] !== 0) { return false; } } if (matrix[4 * 3 + 3] !== 1) { return false; } for (let j = 0; j < 3; j++) { let k = 0; for (let i = 0; i < 3; i++) { if (matrix[4 * j + i] !== 0) { k++; } } if (k !== 1) { return false; } } return true; };
publicAPI.isIdentityMatrix = (matrix) => { for (let i = 0; i < 4; ++i) { for (let j = 0; j < 4; ++j) { if ((i === j ? 1.0 : 0.0) !== matrix[4 * j + i]) { return false; } } } return true; };
publicAPI.isPerspectiveMatrix = (matrix) => matrix[4 * 0 + 3] !== 0 || matrix[4 * 1 + 3] !== 0 || matrix[4 * 2 + 3] !== 0 || matrix[4 * 3 + 3] !== 1;
publicAPI.canUseNearestNeighbor = (matrix, outExt) => { for (let i = 0; i < 3; i++) { let j; for (j = 0; j < 3; j++) { if (matrix[4 * j + i] !== 0) { break; } } if (j >= 3) { return false; } let x = matrix[4 * j + i]; let y = matrix[4 * 3 + i]; if (outExt[2 * j] === outExt[2 * j + 1]) { y += x * outExt[2 * i]; x = 0; } const fx = vtkInterpolationMathFloor(x, 0).error; const fy = vtkInterpolationMathFloor(y, 0).error; if (fx !== 0 || fy !== 0) { return false; } } return true; }; }
const DEFAULT_VALUES = { transformInputSampling: true, autoCropOutput: false, outputDimensionality: 3, outputSpacing: null, outputOrigin: null, outputDirection: null, outputExtent: null, outputScalarType: null, wrap: false, mirror: false, border: true, interpolationMode: InterpolationMode.NEAREST, slabMode: SlabMode.MIN, slabTrapezoidIntegration: false, slabNumberOfSlices: 1, slabSliceSpacingFraction: 1, optimization: false, scalarShift: 0, scalarScale: 1, backgroundColor: [0, 0, 0, 0], resliceAxes: null, interpolator: vtkImageInterpolator.newInstance(), usePermuteExecute: false, };
export function extend(publicAPI, model, initialValues = {}) { Object.assign(model, DEFAULT_VALUES, initialValues);
macro.obj(publicAPI, model);
macro.algo(publicAPI, model, 1, 1);
macro.setGet(publicAPI, model, [ 'outputDimensionality', 'outputScalarType', 'scalarShift', 'scalarScale', 'transformInputSampling', 'autoCropOutput', 'wrap', 'mirror', 'border', 'interpolationMode', 'resliceTransform', 'slabMode', 'slabTrapezoidIntegration', 'slabNumberOfSlices', 'slabSliceSpacingFraction', ]);
macro.setGetArray(publicAPI, model, ['outputOrigin', 'outputSpacing'], 3); macro.setGetArray(publicAPI, model, ['outputExtent'], 6); macro.setGetArray(publicAPI, model, ['outputDirection'], 9); macro.setGetArray(publicAPI, model, ['backgroundColor'], 4);
macro.get(publicAPI, model, ['resliceAxes']);
vtkImageReslice(publicAPI, model); }
export const newInstance = macro.newInstance(extend, 'vtkImageReslice');
export default { newInstance, extend, ...Constants };
|