import macro from 'vtk.js/Sources/macros'; import vtkDataArray from 'vtk.js/Sources/Common/Core/DataArray'; import Constants from 'vtk.js/Sources/Common/Core/ScalarsToColors/Constants'; import vtkMapper from 'vtk.js/Sources/Rendering/Core/Mapper/Constants';
const { ScalarMappingTarget, VectorMode } = Constants; const { VtkDataTypes } = vtkDataArray; const { ColorMode } = vtkMapper; const { vtkErrorMacro } = macro;
function intColorToUChar(c) { return c; } function floatColorToUChar(c) { return Math.floor(c * 255.0 + 0.5); }
function vtkScalarsToColors(publicAPI, model) { model.classHierarchy.push('vtkScalarsToColors');
publicAPI.setVectorModeToMagnitude = () => publicAPI.setVectorMode(VectorMode.MAGNITUDE); publicAPI.setVectorModeToComponent = () => publicAPI.setVectorMode(VectorMode.COMPONENT); publicAPI.setVectorModeToRGBColors = () => publicAPI.setVectorMode(VectorMode.RGBCOLORS);
publicAPI.build = () => {};
publicAPI.isOpaque = () => true;
publicAPI.setAnnotations = (values, annotations) => { if ((values && !annotations) || (!values && annotations)) { return; }
if (values && annotations && values.length !== annotations.length) { vtkErrorMacro( 'Values and annotations do not have the same number of tuples so ignoring' ); return; }
model.annotationArray = [];
if (annotations && values) { const num = annotations.length; for (let i = 0; i < num; i++) { model.annotationArray.push({ value: values[i], annotation: String(annotations[i]), }); } }
publicAPI.updateAnnotatedValueMap(); publicAPI.modified(); };
publicAPI.setAnnotation = (value, annotation) => { let i = publicAPI.checkForAnnotatedValue(value); let modified = false; if (i >= 0) { if (model.annotationArray[i].annotation !== annotation) { model.annotationArray[i].annotation = annotation; modified = true; } } else { model.annotationArray.push({ value, annotation }); i = model.annotationArray.length - 1; modified = true; } if (modified) { publicAPI.updateAnnotatedValueMap(); publicAPI.modified(); } return i; };
publicAPI.getNumberOfAnnotatedValues = () => model.annotationArray.length;
publicAPI.getAnnotatedValue = (idx) => { if (idx < 0 || idx >= model.annotationArray.length) { return null; } return model.annotationArray[idx].value; };
publicAPI.getAnnotation = (idx) => { if (model.annotationArray[idx] === undefined) { return null; } return model.annotationArray[idx].annotation; };
publicAPI.getAnnotatedValueIndex = (val) => model.annotationArray.length ? publicAPI.checkForAnnotatedValue(val) : -1;
publicAPI.removeAnnotation = (value) => { const i = publicAPI.checkForAnnotatedValue(value); const needToRemove = i >= 0; if (needToRemove) { model.annotationArray.splice(i, 1); publicAPI.updateAnnotatedValueMap(); publicAPI.modified(); } return needToRemove; };
publicAPI.resetAnnotations = () => { model.annotationArray = []; model.annotatedValueMap = []; publicAPI.modified(); };
publicAPI.getAnnotationColor = (val, rgba) => { if (model.indexedLookup) { const i = publicAPI.getAnnotatedValueIndex(val); publicAPI.getIndexedColor(i, rgba); } else { publicAPI.getColor(parseFloat(val), rgba); rgba[3] = 1.0; } };
publicAPI.checkForAnnotatedValue = (value) => publicAPI.getAnnotatedValueIndexInternal(value);
publicAPI.getAnnotatedValueIndexInternal = (value) => { if (model.annotatedValueMap[value] !== undefined) { const na = model.annotationArray.length; return model.annotatedValueMap[value] % na; } return -1; };
publicAPI.getIndexedColor = (val, rgba) => { rgba[0] = 0.0; rgba[1] = 0.0; rgba[2] = 0.0; rgba[3] = 0.0; };
publicAPI.updateAnnotatedValueMap = () => { model.annotatedValueMap = [];
const na = model.annotationArray.length; for (let i = 0; i < na; i++) { model.annotatedValueMap[model.annotationArray[i].value] = i; } };
publicAPI.mapScalars = (scalars, colorMode, componentIn) => { const numberOfComponents = scalars.getNumberOfComponents();
let newColors = null;
if ( (colorMode === ColorMode.DEFAULT && (scalars.getDataType() === VtkDataTypes.UNSIGNED_CHAR || scalars.getDataType() === VtkDataTypes.UNSIGNED_CHAR_CLAMPED)) || (colorMode === ColorMode.DIRECT_SCALARS && scalars) ) { newColors = publicAPI.convertToRGBA( scalars, numberOfComponents, scalars.getNumberOfTuples() ); } else { const newscalars = { type: 'vtkDataArray', name: 'temp', numberOfComponents: 4, dataType: VtkDataTypes.UNSIGNED_CHAR, };
const s = macro.newTypedArray( newscalars.dataType, 4 * scalars.getNumberOfTuples() ); newscalars.values = s; newscalars.size = s.length; newColors = vtkDataArray.newInstance(newscalars);
let component = componentIn;
if (component < 0 && numberOfComponents > 1) { publicAPI.mapVectorsThroughTable( scalars, newColors, ScalarMappingTarget.RGBA, -1, -1 ); } else { if (component < 0) { component = 0; } if (component >= numberOfComponents) { component = numberOfComponents - 1; }
publicAPI.mapScalarsThroughTable( scalars, newColors, ScalarMappingTarget.RGBA, component ); } }
return newColors; };
publicAPI.mapVectorsToMagnitude = (input, output, compsToUse) => { const length = input.getNumberOfTuples(); const inIncr = input.getNumberOfComponents();
const outputV = output.getData(); const inputV = input.getData();
for (let i = 0; i < length; i++) { let sum = 0.0; for (let j = 0; j < compsToUse; j++) { sum += inputV[i * inIncr + j] * inputV[i * inIncr + j]; } outputV[i] = Math.sqrt(sum); } };
publicAPI.mapVectorsThroughTable = ( input, output, outputFormat, vectorComponentIn, vectorSizeIn ) => { let vectorMode = publicAPI.getVectorMode(); let vectorSize = vectorSizeIn; let vectorComponent = vectorComponentIn; const inComponents = input.getNumberOfComponents();
if (vectorMode === VectorMode.COMPONENT) { if (vectorComponent === -1) { vectorComponent = publicAPI.getVectorComponent(); } if (vectorComponent < 0) { vectorComponent = 0; } if (vectorComponent >= inComponents) { vectorComponent = inComponents - 1; } } else { if (vectorSize === -1) { vectorSize = publicAPI.getVectorSize(); } if (vectorSize <= 0) { vectorComponent = 0; vectorSize = inComponents; } else { if (vectorComponent < 0) { vectorComponent = 0; } if (vectorComponent >= inComponents) { vectorComponent = inComponents - 1; } if (vectorComponent + vectorSize > inComponents) { vectorSize = inComponents - vectorComponent; } }
if ( vectorMode === VectorMode.MAGNITUDE && (inComponents === 1 || vectorSize === 1) ) { vectorMode = VectorMode.COMPONENT; } }
let inputOffset = 0; if (vectorComponent > 0) { inputOffset = vectorComponent; }
switch (vectorMode) { case VectorMode.COMPONENT: { publicAPI.mapScalarsThroughTable( input, output, outputFormat, inputOffset ); break; }
case VectorMode.RGBCOLORS: { break; }
case VectorMode.MAGNITUDE: default: { const magValues = vtkDataArray.newInstance({ numberOfComponents: 1, values: new Float32Array(input.getNumberOfTuples()), });
publicAPI.mapVectorsToMagnitude(input, magValues, vectorSize); publicAPI.mapScalarsThroughTable(magValues, output, outputFormat, 0); break; } } };
publicAPI.luminanceToRGBA = (newColors, colors, alpha, convtFun) => { const a = convtFun(alpha);
const values = colors.getData(); const newValues = newColors.getData(); const size = values.length; const component = 0; const tuple = 1;
let count = 0; for (let i = component; i < size; i += tuple) { const l = convtFun(values[i]); newValues[count * 4] = l; newValues[count * 4 + 1] = l; newValues[count * 4 + 2] = l; newValues[count * 4 + 3] = a; count++; } };
publicAPI.luminanceAlphaToRGBA = (newColors, colors, alpha, convtFun) => { const values = colors.getData(); const newValues = newColors.getData(); const size = values.length; const component = 0; const tuple = 2;
let count = 0; for (let i = component; i < size; i += tuple) { const l = convtFun(values[i]); newValues[count] = l; newValues[count + 1] = l; newValues[count + 2] = l; newValues[count + 3] = convtFun(values[i + 1]) * alpha; count += 4; } };
publicAPI.rGBToRGBA = (newColors, colors, alpha, convtFun) => { const a = floatColorToUChar(alpha);
const values = colors.getData(); const newValues = newColors.getData(); const size = values.length; const component = 0; const tuple = 3;
let count = 0; for (let i = component; i < size; i += tuple) { newValues[count * 4] = convtFun(values[i]); newValues[count * 4 + 1] = convtFun(values[i + 1]); newValues[count * 4 + 2] = convtFun(values[i + 2]); newValues[count * 4 + 3] = a; count++; } };
publicAPI.rGBAToRGBA = (newColors, colors, alpha, convtFun) => { const values = colors.getData(); const newValues = newColors.getData(); const size = values.length; const component = 0; const tuple = 4;
let count = 0; for (let i = component; i < size; i += tuple) { newValues[count * 4] = convtFun(values[i]); newValues[count * 4 + 1] = convtFun(values[i + 1]); newValues[count * 4 + 2] = convtFun(values[i + 2]); newValues[count * 4 + 3] = convtFun(values[i + 3]) * alpha; count++; } };
publicAPI.convertToRGBA = (colors, numComp, numTuples) => { let { alpha } = model; if ( numComp === 4 && alpha >= 1.0 && colors.getDataType() === VtkDataTypes.UNSIGNED_CHAR ) { return colors; }
const newColors = vtkDataArray.newInstance({ numberOfComponents: 4, empty: true, size: 4 * numTuples, dataType: VtkDataTypes.UNSIGNED_CHAR, });
if (numTuples <= 0) { return newColors; }
alpha = alpha > 0 ? alpha : 0; alpha = alpha < 1 ? alpha : 1;
let convtFun = intColorToUChar; if ( colors.getDataType() === VtkDataTypes.FLOAT || colors.getDataType() === VtkDataTypes.DOUBLE ) { convtFun = floatColorToUChar; }
switch (numComp) { case 1: publicAPI.luminanceToRGBA(newColors, colors, alpha, convtFun); break;
case 2: publicAPI.luminanceAlphaToRGBA(newColors, colors, convtFun); break;
case 3: publicAPI.rGBToRGBA(newColors, colors, alpha, convtFun); break;
case 4: publicAPI.rGBAToRGBA(newColors, colors, alpha, convtFun); break;
default: vtkErrorMacro('Cannot convert colors'); return null; }
return newColors; };
publicAPI.usingLogScale = () => false;
publicAPI.getNumberOfAvailableColors = () => 256 * 256 * 256;
publicAPI.setRange = (min, max) => publicAPI.setMappingRange(min, max); publicAPI.getRange = () => publicAPI.getMappingRange();
publicAPI.areScalarsOpaque = (scalars, colorMode, componentIn) => { if (!scalars) { return publicAPI.isOpaque(); }
const numberOfComponents = scalars.getNumberOfComponents();
if ( (colorMode === ColorMode.DEFAULT && scalars.getDataType() === VtkDataTypes.UNSIGNED_CHAR) || colorMode === ColorMode.DIRECT_SCALARS ) { if (numberOfComponents === 3 || numberOfComponents === 1) { return model.alpha >= 1.0; } const range = scalars.getRange(numberOfComponents - 1); return range[0] === 255; }
return true; }; }
const DEFAULT_VALUES = { alpha: 1.0, vectorComponent: 0, vectorSize: -1, vectorMode: VectorMode.COMPONENT, mappingRange: null, annotationArray: null, annotatedValueMap: null, indexedLookup: false, };
export function extend(publicAPI, model, initialValues = {}) { Object.assign(model, DEFAULT_VALUES, initialValues);
macro.obj(publicAPI, model);
model.mappingRange = [0, 255]; model.annotationArray = []; model.annotatedValueMap = [];
macro.setGet(publicAPI, model, [ 'vectorSize', 'vectorComponent', 'vectorMode', 'alpha', 'indexedLookup', ]);
macro.setArray(publicAPI, model, ['mappingRange'], 2);
macro.getArray(publicAPI, model, ['mappingRange']);
vtkScalarsToColors(publicAPI, model); }
export const newInstance = macro.newInstance(extend, 'vtkScalarsToColors');
export default { newInstance, extend, ...Constants };
|