@thewtex/vtk.js-esm
Version:
Visualization Toolkit for the Web
1,023 lines (813 loc) • 34.7 kB
JavaScript
import _defineProperty from '@babel/runtime/helpers/defineProperty';
import macro from '../../macro.js';
import vtkDataArray from '../../Common/Core/DataArray.js';
import { VtkDataTypes } from '../../Common/Core/DataArray/Constants.js';
import vtkBoundingBox from '../../Common/DataModel/BoundingBox.js';
import vtkImageData from '../../Common/DataModel/ImageData.js';
import vtkImageInterpolator from './ImageInterpolator.js';
import vtkImagePointDataIterator from './ImagePointDataIterator.js';
import { InterpolationMode, ImageBorderMode } from './AbstractImageInterpolator/Constants.js';
import { vtkInterpolationMathRound, vtkInterpolationMathClamp, vtkInterpolationMathFloor } from './AbstractImageInterpolator/InterpolationInfo.js';
import Constants from './ImageReslice/Constants.js';
import { i as identity, h as exactEquals, d as copy, g as invert, m as multiply } from '../../vendor/gl-matrix/esm/mat4.js';
import { t as transformMat4 } from '../../vendor/gl-matrix/esm/vec4.js';
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
var SlabMode = Constants.SlabMode;
var capitalize = macro.capitalize,
vtkErrorMacro = macro.vtkErrorMacro; // ----------------------------------------------------------------------------
// vtkImageReslice methods
// ----------------------------------------------------------------------------
function vtkImageReslice(publicAPI, model) {
// Set our className
model.classHierarchy.push('vtkImageReslice');
var indexMatrix = null;
var optimizedTransform = null;
function getImageResliceSlabTrap(tmpPtr, inComponents, sampleCount, f) {
var n = sampleCount - 1;
for (var i = 0; i < inComponents; i += 1) {
var result = tmpPtr[i] * 0.5;
for (var 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 (var i = 0; i < inComponents; i += 1) {
var result = tmpPtr[i];
for (var j = 1; j < sampleCount; j += 1) {
result += tmpPtr[i + j * inComponents];
}
tmpPtr[i] = result * f;
}
}
function getImageResliceCompositeMinValue(tmpPtr, inComponents, sampleCount) {
for (var i = 0; i < inComponents; i += 1) {
var result = tmpPtr[i];
for (var j = 1; j < sampleCount; j += 1) {
result = Math.min(result, tmpPtr[i + j * inComponents]);
}
tmpPtr[i] = result;
}
}
function getImageResliceCompositeMaxValue(tmpPtr, inComponents, sampleCount) {
for (var i = 0; i < inComponents; i += 1) {
var result = tmpPtr[i];
for (var j = 1; j < sampleCount; j += 1) {
result = Math.max(result, tmpPtr[i + j * inComponents]);
}
tmpPtr[i] = result;
}
}
function getImageResliceCompositeMeanValue(tmpPtr, inComponents, sampleCount) {
var f = 1.0 / sampleCount;
getImageResliceSlabSum(tmpPtr, inComponents, sampleCount, f);
}
function getImageResliceCompositeMeanTrap(tmpPtr, inComponents, sampleCount) {
var f = 1.0 / (sampleCount - 1);
getImageResliceSlabTrap(tmpPtr, inComponents, sampleCount, f);
}
function getImageResliceCompositeSumValue(tmpPtr, inComponents, sampleCount) {
var f = 1.0;
getImageResliceSlabSum(tmpPtr, inComponents, sampleCount, f);
}
function getImageResliceCompositeSumTrap(tmpPtr, inComponents, sampleCount) {
var f = 1.0;
getImageResliceSlabTrap(tmpPtr, inComponents, sampleCount, f);
}
publicAPI.setResliceAxes = function (resliceAxes) {
if (!model.resliceAxes) {
model.resliceAxes = identity(new Float64Array(16));
}
if (!exactEquals(model.resliceAxes, resliceAxes)) {
copy(model.resliceAxes, resliceAxes);
publicAPI.modified();
return true;
}
return null;
};
publicAPI.requestData = function (inData, outData) {
// implement requestData
var input = inData[0];
if (!input) {
vtkErrorMacro('Invalid or missing input');
return;
} // console.time('reslice');
// Retrieve output and volume data
var origin = input.getOrigin();
var inSpacing = input.getSpacing();
var dims = input.getDimensions();
var inScalars = input.getPointData().getScalars();
var inWholeExt = [0, dims[0] - 1, 0, dims[1] - 1, 0, dims[2] - 1];
var outOrigin = [0, 0, 0];
var outSpacing = [1, 1, 1];
var outWholeExt = [0, 0, 0, 0, 0, 0];
var outDims = [0, 0, 0];
var matrix = null;
if (model.resliceAxes) {
matrix = model.resliceAxes;
} else {
matrix = identity(new Float64Array(16));
}
var imatrix = new Float64Array(16);
invert(imatrix, matrix);
var 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]];
var maxBounds = null;
if (model.autoCropOutput) {
maxBounds = publicAPI.getAutoCroppedOutputBounds(input);
}
for (var i = 0; i < 3; i++) {
var s = 0; // default output spacing
var d = 0; // default linear dimension
var e = 0; // default extent start
var c = 0; // transformed center-of-volume
if (model.transformInputSampling) {
var r = 0.0;
for (var j = 0; j < 3; j++) {
c += imatrix[4 * j + i] * (inCenter[j] - matrix[4 * 3 + j]);
var 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) {
// set origin so edge of extent is edge of bounds
outOrigin[i] = maxBounds[2 * i] - outWholeExt[2 * i] * outSpacing[i];
} else {
// center new bounds over center of input bounds
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;
}
var dataType = inScalars.getDataType();
if (model.outputScalarType) {
dataType = model.outputScalarType;
}
var numComponents = input.getPointData().getScalars().getNumberOfComponents(); // or s.numberOfComponents;
var outScalarsData = macro.newTypedArray(dataType, outDims[0] * outDims[1] * outDims[2] * numComponents);
var outScalars = vtkDataArray.newInstance({
name: 'Scalars',
values: outScalarsData,
numberOfComponents: numComponents
}); // Update output
var output = vtkImageData.newInstance();
output.setDimensions(outDims);
output.setOrigin(outOrigin);
output.setSpacing(outSpacing);
output.getPointData().setScalars(outScalars);
publicAPI.getIndexMatrix(input, output);
var interpolationMode = model.interpolationMode;
model.usePermuteExecute = false;
if (model.optimization) {
if (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);
var borderMode = ImageBorderMode.CLAMP;
borderMode = model.wrap ? ImageBorderMode.REPEAT : borderMode;
borderMode = model.mirror ? ImageBorderMode.MIRROR : borderMode;
model.interpolator.setBorderMode(borderMode);
var mintol = 7.62939453125e-6;
var maxtol = 2.0 * 2147483647;
var 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; // console.timeEnd('reslice');
};
publicAPI.vtkImageResliceExecute = function (input, output) {
// const outDims = output.getDimensions();
var inScalars = input.getPointData().getScalars();
var outScalars = output.getPointData().getScalars();
var outPtr = outScalars.getData();
var outExt = output.getExtent();
var newmat = indexMatrix;
var nsamples = Math.max(model.slabNumberOfSlices, 1); // spacing between slab samples (as a fraction of slice spacing).
var slabSampleSpacing = model.slabSliceSpacingFraction; // check for perspective transformation
var perspective = publicAPI.isPerspectiveMatrix(newmat); // extra scalar info for nearest-neighbor optimization
var inPtr = inScalars.getData();
var inputScalarSize = 1; // inScalars.getElementComponentSize(); // inScalars.getDataTypeSize();
var inputScalarType = inScalars.getDataType();
var inComponents = inScalars.getNumberOfComponents(); // interpolator.GetNumberOfComponents();
var componentOffset = model.interpolator.getComponentOffset();
var borderMode = model.interpolator.getBorderMode();
var inDims = input.getDimensions();
var inExt = [0, inDims[0] - 1, 0, inDims[1] - 1, 0, inDims[2] - 1]; // interpolator->GetExtent();
var inInc = [0, 0, 0];
inInc[0] = inScalars.getNumberOfComponents();
inInc[1] = inInc[0] * inDims[0];
inInc[2] = inInc[1] * inDims[1];
var fullSize = inDims[0] * inDims[1] * inDims[2];
if (componentOffset > 0 && componentOffset + inComponents < inInc[0]) {
inPtr = inPtr.subarray(inputScalarSize * componentOffset);
}
var interpolationMode = InterpolationMode.NEAREST;
if (model.interpolator.isA('vtkImageInterpolator')) {
interpolationMode = model.interpolator.getInterpolationMode();
}
var convertScalars = null;
var rescaleScalars = model.scalarShift !== 0.0 || model.scalarScale !== 1.0; // is nearest neighbor optimization possible?
var optimizeNearest = interpolationMode === InterpolationMode.NEAREST && borderMode === ImageBorderMode.CLAMP && !(perspective || convertScalars != null || rescaleScalars) && inputScalarType === outScalars.getDataType() && fullSize === inScalars.getNumberOfTuples() && model.border === true && nsamples <= 1; // get pixel information
var scalarType = outScalars.getDataType();
var scalarSize = 1; // outScalars.getElementComponentSize() // outScalars.scalarSize;
var outComponents = outScalars.getNumberOfComponents(); // break matrix into a set of axes plus an origin
// (this allows us to calculate the transform Incrementally)
var xAxis = [0, 0, 0, 0];
var yAxis = [0, 0, 0, 0];
var zAxis = [0, 0, 0, 0];
var origin = [0, 0, 0, 0];
for (var 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];
} // get the input origin and spacing for conversion purposes
model.interpolator.getOrigin();
var inSpacing = model.interpolator.getSpacing();
[1.0 / inSpacing[0], 1.0 / inSpacing[1], 1.0 / inSpacing[2]]; // allocate an output row of type double
var floatPtr = null;
if (!optimizeNearest) {
floatPtr = new Float64Array(inComponents * (outExt[1] - outExt[0]));
}
var background = macro.newTypedArray(inputScalarType, model.backgroundColor); // set color for area outside of input volume extent
// void *background;
// vtkAllocBackgroundPixel(&background,
// self->GetBackgroundColor(), scalarType, scalarSize, outComponents);
// get various helper functions
var forceClamping = interpolationMode > InterpolationMode.LINEAR || nsamples > 1 && model.slabMode === SlabMode.SUM;
var convertpixels = publicAPI.getConversionFunc(inputScalarType, scalarType, model.scalarShift, model.scalarScale, forceClamping);
var setpixels = publicAPI.getSetPixelsFunc(scalarType, scalarSize, outComponents, outPtr);
var composite = publicAPI.getCompositeFunc(model.slabMode, model.slabTrapezoidIntegration); // create some variables for when we march through the data
var idY = outExt[2] - 1;
var idZ = outExt[4] - 1;
var inPoint0 = [0.0, 0.0, 0.0, 0.0];
var inPoint1 = [0.0, 0.0, 0.0, 0.0]; // create an iterator to march through the data
var iter = vtkImagePointDataIterator.newInstance();
iter.initialize(output, outExt, model.stencil, null);
var outPtr0 = iter.getScalars(output, 0);
var outPtrIndex = 0;
var outTmp = macro.newTypedArray(scalarType, vtkBoundingBox.getDiagonalLength(outExt) * outComponents * 2);
var interpolatedPtr = new Float64Array(inComponents * nsamples);
var interpolatedPoint = new Float64Array(inComponents);
for (; !iter.isAtEnd(); iter.nextSpan()) {
var span = iter.spanEndId() - iter.getId();
outPtrIndex = iter.getId() * scalarSize * outComponents;
if (!iter.isInStencil()) {
// clear any regions that are outside the stencil
var n = setpixels(outTmp, background, outComponents, span);
for (var _i = 0; _i < n; ++_i) {
outPtr0[outPtrIndex++] = outTmp[_i];
}
} else {
// get output index, and compute position in input image
var outIndex = iter.getIndex(); // if Z index increased, then advance position along Z axis
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 Y index increased, then advance position along Y axis
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];
} // march through one row of the output image
var idXmin = outIndex[0];
var idXmax = idXmin + span - 1;
if (!optimizeNearest) {
var wasInBounds = 1;
var isInBounds = 1;
var startIdX = idXmin;
var idX = idXmin;
var tmpPtr = floatPtr;
var pixelIndex = 0;
while (startIdX <= idXmax) {
for (; idX <= idXmax && isInBounds === wasInBounds; idX++) {
var inPoint2 = [inPoint1[0] + idX * xAxis[0], inPoint1[1] + idX * xAxis[1], inPoint1[2] + idX * xAxis[2], inPoint1[3] + idX * xAxis[3]];
var inPoint3 = [0, 0, 0, 0];
var inPoint = inPoint2;
isInBounds = false;
var interpolatedPtrIndex = 0;
for (var sample = 0; sample < nsamples; ++sample) {
if (nsamples > 1) {
var 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) {
// only do perspective if necessary
var f = 1 / inPoint[3];
inPoint[0] *= f;
inPoint[1] *= f;
inPoint[2] *= f;
}
if (model.interpolator.checkBoundsIJK(inPoint)) {
// do the interpolation
isInBounds = 1;
model.interpolator.interpolateIJK(inPoint, interpolatedPoint);
for (var _i2 = 0; _i2 < inComponents; ++_i2) {
interpolatedPtr[interpolatedPtrIndex++] = interpolatedPoint[_i2];
}
}
}
if (interpolatedPtrIndex > inComponents) {
composite(interpolatedPtr, inComponents, interpolatedPtrIndex / inComponents);
}
for (var _i3 = 0; _i3 < inComponents; ++_i3) {
tmpPtr[pixelIndex++] = interpolatedPtr[_i3];
} // set "was in" to "is in" if first pixel
wasInBounds = idX > idXmin ? wasInBounds : isInBounds;
} // write a segment to the output
var endIdX = idX - 1 - (isInBounds !== wasInBounds);
var numpixels = endIdX - startIdX + 1;
var _n = 0;
if (wasInBounds) {
if (rescaleScalars) {
publicAPI.rescaleScalars(floatPtr, inComponents, idXmax - idXmin + 1, model.scalarShift, model.scalarScale);
}
{
_n = convertpixels(outTmp, floatPtr.subarray(startIdX * inComponents), outComponents, numpixels);
}
} else {
_n = setpixels(outTmp, background, outComponents, numpixels);
}
for (var _i4 = 0; _i4 < _n; ++_i4) {
outPtr0[outPtrIndex++] = outTmp[_i4];
}
startIdX += numpixels;
wasInBounds = isInBounds;
}
} else {
// optimize for nearest-neighbor interpolation
var inPtrTmp0 = inPtr;
var outPtrTmp = outPtr;
var inIncX = inInc[0] * inputScalarSize;
var inIncY = inInc[1] * inputScalarSize;
var inIncZ = inInc[2] * inputScalarSize;
var inExtX = inExt[1] - inExt[0] + 1;
var inExtY = inExt[3] - inExt[2] + 1;
var inExtZ = inExt[5] - inExt[4] + 1;
var _startIdX = idXmin;
var _endIdX = idXmin - 1;
var _isInBounds = false;
var bytesPerPixel = inputScalarSize * inComponents;
for (var iidX = idXmin; iidX <= idXmax; iidX++) {
var _inPoint = [inPoint1[0] + iidX * xAxis[0], inPoint1[1] + iidX * xAxis[1], inPoint1[2] + iidX * xAxis[2]];
var inIdX = vtkInterpolationMathRound(_inPoint[0]) - inExt[0];
var inIdY = vtkInterpolationMathRound(_inPoint[1]) - inExt[2];
var inIdZ = vtkInterpolationMathRound(_inPoint[2]) - inExt[4];
if (inIdX >= 0 && inIdX < inExtX && inIdY >= 0 && inIdY < inExtY && inIdZ >= 0 && inIdZ < inExtZ) {
if (!_isInBounds) {
// clear leading out-of-bounds pixels
_startIdX = iidX;
_isInBounds = true;
var _n3 = setpixels(outTmp, background, outComponents, _startIdX - idXmin);
for (var _i5 = 0; _i5 < _n3; ++_i5) {
outPtr0[outPtrIndex++] = outTmp[_i5];
}
} // set the final index that was within input bounds
_endIdX = iidX; // perform nearest-neighbor interpolation via pixel copy
var offset = inIdX * inIncX + inIdY * inIncY + inIdZ * inIncZ; // when memcpy is used with a constant size, the compiler will
// optimize away the function call and use the minimum number
// of instructions necessary to perform the copy
switch (bytesPerPixel) {
case 1:
outPtr0[outPtrIndex++] = inPtrTmp0[offset];
break;
case 2:
case 3:
case 4:
case 8:
case 12:
case 16:
for (var _i6 = 0; _i6 < bytesPerPixel; ++_i6) {
outPtr0[outPtrIndex++] = inPtrTmp0[offset + _i6];
}
break;
default:
{
// TODO: check bytes
var oc = 0;
do {
outPtr0[outPtrIndex++] = inPtrTmp0[offset++];
} while (++oc !== bytesPerPixel);
break;
}
}
} else if (_isInBounds) {
// leaving input bounds
break;
}
} // clear trailing out-of-bounds pixels
outPtr = outPtrTmp;
var _n2 = setpixels(outTmp, background, outComponents, idXmax - _endIdX);
for (var _i7 = 0; _i7 < _n2; ++_i7) {
outPtr0[outPtrIndex++] = outTmp[_i7];
}
}
}
}
};
publicAPI.getIndexMatrix = function (input, output) {
// first verify that we have to update the matrix
if (indexMatrix === null) {
indexMatrix = identity(new Float64Array(16));
}
var inOrigin = input.getOrigin();
var inSpacing = input.getSpacing();
var outOrigin = output.getOrigin();
var outSpacing = output.getSpacing();
var transform = identity(new Float64Array(16));
var inMatrix = identity(new Float64Array(16));
var outMatrix = identity(new Float64Array(16));
if (model.resliceAxes) {
copy(transform, model.resliceAxes);
}
if (model.resliceTransform) ; // check to see if we have an identity matrix
var isIdentity = publicAPI.isIdentityMatrix(transform); // the outMatrix takes OutputData indices to OutputData coordinates,
// the inMatrix takes InputData coordinates to InputData indices
for (var i = 0; i < 3; i++) {
if ((inSpacing[i] !== outSpacing[i] || inOrigin[i] !== outOrigin[i]) || optimizedTransform !== null ) {
isIdentity = false;
}
inMatrix[4 * i + i] = 1.0 / inSpacing[i];
inMatrix[4 * 3 + i] = -inOrigin[i] / inSpacing[i];
outMatrix[4 * i + i] = outSpacing[i];
outMatrix[4 * 3 + i] = outOrigin[i];
}
if (!isIdentity) {
// transform.PreMultiply();
// transform.Concatenate(outMatrix);
multiply(transform, transform, outMatrix); // the optimizedTransform requires data coords, not
// index coords, as its input
{
// transform->PostMultiply();
// transform->Concatenate(inMatrix);
multiply(transform, inMatrix, transform);
}
}
copy(indexMatrix, transform);
return indexMatrix;
};
publicAPI.getAutoCroppedOutputBounds = function (input) {
var inOrigin = input.getOrigin();
var inSpacing = input.getSpacing();
var dims = input.getDimensions();
var inWholeExt = [0, dims[0] - 1, 0, dims[1] - 1, 0, dims[2] - 1];
var matrix = new Float64Array(16);
if (model.resliceAxes) {
invert(matrix, model.resliceAxes);
} else {
identity(matrix);
}
var bounds = [Number.MAX_VALUE, -Number.MAX_VALUE, Number.MAX_VALUE, -Number.MAX_VALUE, Number.MAX_VALUE, -Number.MAX_VALUE];
var point = [0, 0, 0, 0];
for (var 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 (model.resliceTransform) ;
transformMat4(point, point, matrix);
var f = 1.0 / point[3];
point[0] *= f;
point[1] *= f;
point[2] *= f;
for (var 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 = function (dataType) {
switch (dataType) {
case 'Int8Array':
return {
min: -128,
max: 127
};
case 'Uint8Array':
case 'Uint8ClampedArray':
default:
return {
min: 0,
max: 255
};
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
};
}
};
publicAPI.clamp = function (outPtr, inPtr, numscalars, n, min, max) {
var count = n * numscalars;
for (var i = 0; i < count; ++i) {
outPtr[i] = vtkInterpolationMathClamp(inPtr[i], min, max);
}
return count;
};
publicAPI.convert = function (outPtr, inPtr, numscalars, n) {
var count = n * numscalars;
for (var i = 0; i < count; ++i) {
outPtr[i] = Math.round(inPtr[i]);
}
return count;
};
publicAPI.getConversionFunc = function (inputType, dataType, scalarShift, scalarScale, forceClamping) {
var useClamping = forceClamping;
if (dataType !== VtkDataTypes.FLOAT && dataType !== VtkDataTypes.DOUBLE && !forceClamping) {
var inMinMax = publicAPI.getDataTypeMinMax(inputType);
var checkMin = (inMinMax.min + scalarShift) * scalarScale;
var checkMax = (inMinMax.max + scalarShift) * scalarScale;
var outMinMax = publicAPI.getDataTypeMinMax(dataType);
var outputMin = outMinMax.min;
var outputMax = outMinMax.max;
if (checkMin > checkMax) {
var tmp = checkMax;
checkMax = checkMin;
checkMin = tmp;
}
useClamping = checkMin < outputMin || checkMax > outputMax;
}
if (useClamping && dataType !== VtkDataTypes.FLOAT && dataType !== VtkDataTypes.DOUBLE) {
var minMax = publicAPI.getDataTypeMinMax(dataType);
var clamp = function clamp(outPtr, inPtr, numscalars, n) {
return publicAPI.clamp(outPtr, inPtr, numscalars, n, minMax.min, minMax.max);
};
return clamp;
}
return publicAPI.convert;
};
publicAPI.set = function (outPtr, inPtr, numscalars, n) {
var count = numscalars * n;
for (var i = 0; i < n; ++i) {
outPtr[i] = inPtr[i];
}
return count;
};
publicAPI.set1 = function (outPtr, inPtr, numscalars, n) {
outPtr.fill(inPtr[0], 0, n);
return n;
};
publicAPI.getSetPixelsFunc = function (dataType, dataSize, numscalars, dataPtr) {
return numscalars === 1 ? publicAPI.set1 : publicAPI.set;
};
publicAPI.getCompositeFunc = function (slabMode, slabTrapezoidIntegration) {
var composite = null; // eslint-disable-next-line default-case
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 = function (newTrans, inPoint, inOrigin, inInvSpacing) {
inPoint[3] = 1;
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 = function (floatData, components, n, scalarShift, scalarScale) {
var m = n * components;
for (var i = 0; i < m; ++i) {
floatData[i] = (floatData[i] + scalarShift) * scalarScale;
}
};
publicAPI.isPermutationMatrix = function (matrix) {
for (var i = 0; i < 3; i++) {
if (matrix[4 * i + 3] !== 0) {
return false;
}
}
if (matrix[4 * 3 + 3] !== 1) {
return false;
}
for (var j = 0; j < 3; j++) {
var k = 0;
for (var _i8 = 0; _i8 < 3; _i8++) {
if (matrix[4 * j + _i8] !== 0) {
k++;
}
}
if (k !== 1) {
return 0;
}
}
return 1;
}; // TODO: to move in vtkMath and add tolerance
publicAPI.isIdentityMatrix = function (matrix) {
for (var i = 0; i < 4; ++i) {
for (var j = 0; j < 4; ++j) {
if ((i === j ? 1.0 : 0.0) !== matrix[4 * j + i]) {
return false;
}
}
}
return true;
};
publicAPI.isPerspectiveMatrix = function (matrix) {
return matrix[4 * 0 + 3] !== 0 || matrix[4 * 1 + 3] !== 0 || matrix[4 * 2 + 3] !== 0 || matrix[4 * 3 + 3] !== 1;
};
publicAPI.canUseNearestNeighbor = function (matrix, outExt) {
// loop through dimensions
for (var i = 0; i < 3; i++) {
var j = void 0;
for (j = 0; j < 3; j++) {
if (matrix[4 * j + i] !== 0) {
break;
}
}
if (j >= 3) {
return 0;
}
var x = matrix[4 * j + i];
var y = matrix[4 * 3 + i];
if (outExt[2 * j] === outExt[2 * j + 1]) {
y += x * outExt[2 * i];
x = 0;
}
var fx = vtkInterpolationMathFloor(x).error;
var fy = vtkInterpolationMathFloor(y).error;
if (fx !== 0 || fy !== 0) {
return 0;
}
}
return 1;
};
}
function setNullArray(publicAPI, model, fieldNames) {
fieldNames.forEach(function (field) {
var setterName = "set".concat(capitalize(field));
var superSet = publicAPI[setterName];
publicAPI[setterName] = function () {
if (arguments.length === 1 && (arguments.length <= 0 ? undefined : arguments[0]) == null || model[field] == null) {
if ((arguments.length <= 0 ? undefined : arguments[0]) !== model[field]) {
model[field] = arguments.length <= 0 ? undefined : arguments[0];
publicAPI.modified();
return true;
}
return null;
}
return superSet.apply(void 0, arguments);
};
});
} // ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------
var DEFAULT_VALUES = {
transformInputSampling: true,
autoCropOutput: false,
outputDimensionality: 3,
outputSpacing: null,
// automatically computed if null
outputOrigin: null,
// automatically computed if null
outputExtent: null,
// automatically computed if null
outputScalarType: null,
wrap: false,
// don't wrap
mirror: false,
// don't mirror
border: true,
// apply a border
interpolationMode: InterpolationMode.NEAREST,
// only NEAREST supported so far
slabMode: SlabMode.MIN,
slabTrapezoidIntegration: false,
slabNumberOfSlices: 1,
slabSliceSpacingFraction: 1,
optimization: false,
// not supported yet
scalarShift: 0,
// for rescaling the data
scalarScale: 1,
backgroundColor: [0, 0, 0, 0],
resliceAxes: null,
resliceTransform: null,
interpolator: vtkImageInterpolator.newInstance(),
usePermuteExecute: false // no supported yet
}; // ----------------------------------------------------------------------------
function extend(publicAPI, model) {
var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
Object.assign(model, DEFAULT_VALUES, initialValues); // Make this a VTK object
macro.obj(publicAPI, model); // Also make it an algorithm with one input and one output
macro.algo(publicAPI, model, 1, 1);
macro.setGet(publicAPI, model, ['outputDimensionality', 'outputScalarType', 'scalarShift', 'scalarScale', 'transformInputSampling', 'autoCropOutput', 'wrap', 'mirror', 'border', 'backgroundColor', 'slabMode', 'slabTrapezoidIntegration', 'slabNumberOfSlices', 'slabSliceSpacingFraction']);
macro.setGetArray(publicAPI, model, ['outputOrigin', 'outputSpacing'], 3);
macro.setGetArray(publicAPI, model, ['outputExtent'], 6);
setNullArray(publicAPI, model, ['outputOrigin', 'outputSpacing', 'outputExtent']);
macro.get(publicAPI, model, ['resliceAxes']); // Object specific methods
macro.algo(publicAPI, model, 1, 1);
vtkImageReslice(publicAPI, model);
} // ----------------------------------------------------------------------------
var newInstance = macro.newInstance(extend, 'vtkImageReslice'); // ----------------------------------------------------------------------------
var vtkImageReslice$1 = _objectSpread({
newInstance: newInstance,
extend: extend
}, Constants);
export default vtkImageReslice$1;
export { extend, newInstance };