UNPKG

@thewtex/vtk.js-esm

Version:

Visualization Toolkit for the Web

1,023 lines (813 loc) 34.7 kB
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 };