import macro from 'vtk.js/Sources/macros'; import * as vtkMath from 'vtk.js/Sources/Common/Core/Math'; import vtkScalarsToColors from 'vtk.js/Sources/Common/Core/ScalarsToColors'; import { ScalarMappingTarget } from 'vtk.js/Sources/Common/Core/ScalarsToColors/Constants';
import { VtkDataTypes } from 'vtk.js/Sources/Common/Core/DataArray/Constants';
const { vtkErrorMacro } = macro;
const BELOW_RANGE_COLOR_INDEX = 0; const ABOVE_RANGE_COLOR_INDEX = 1; const NAN_COLOR_INDEX = 2;
function vtkLookupTable(publicAPI, model) { model.classHierarchy.push('vtkLookupTable');
publicAPI.isOpaque = () => { if (model.opaqueFlagBuildTime.getMTime() < publicAPI.getMTime()) { let opaque = true; if (model.nanColor[3] < 1.0) { opaque = 0; } if (model.useBelowRangeColor && model.belowRangeColor[3] < 1.0) { opaque = 0; } if (model.useAboveRangeColor && model.aboveRangeColor[3] < 1.0) { opaque = 0; } for (let i = 3; i < model.table.length && opaque; i += 4) { if (model.table[i] < 255) { opaque = false; } } model.opaqueFlag = opaque; model.opaqueFlagBuildTime.modified(); }
return model.opaqueFlag; };
publicAPI.usingLogScale = () => false;
publicAPI.getNumberOfAvailableColors = () => model.table.length / 4 - 3;
publicAPI.linearIndexLookup = (v, p) => { let dIndex = 0; const nv = Number(v);
if (nv < p.range[0]) { dIndex = p.maxIndex + BELOW_RANGE_COLOR_INDEX + 1.5; } else if (nv > p.range[1]) { dIndex = p.maxIndex + ABOVE_RANGE_COLOR_INDEX + 1.5; } else { dIndex = (nv + p.shift) * p.scale;
dIndex = dIndex < p.maxIndex ? dIndex : p.maxIndex; }
return Math.floor(dIndex); };
publicAPI.linearLookup = (v, table, p) => { let index = 0; if (vtkMath.isNan(v)) { index = Math.floor(p.maxIndex + 1.5 + NAN_COLOR_INDEX); } else { index = publicAPI.linearIndexLookup(v, p); } const offset = 4 * index; return table.slice(offset, offset + 4); };
publicAPI.indexedLookupFunction = (v, table, p) => { let index = publicAPI.getAnnotatedValueIndexInternal(v); if (index === -1) { index = model.numberOfColors + NAN_COLOR_INDEX; } const offset = 4 * index; return [ table[offset], table[offset + 1], table[offset + 2], table[offset + 3], ]; };
publicAPI.lookupShiftAndScale = (range, p) => { p.shift = -range[0]; p.scale = Number.MAX_VALUE; if (range[1] > range[0]) { p.scale = (p.maxIndex + 1) / (range[1] - range[0]); } };
publicAPI.mapScalarsThroughTable = ( input, output, outFormat, inputOffset ) => { let lookupFunc = publicAPI.linearLookup; if (model.indexedLookup) { lookupFunc = publicAPI.indexedLookupFunction; }
const trange = publicAPI.getMappingRange();
const p = { maxIndex: publicAPI.getNumberOfColors() - 1, range: trange, shift: 0.0, scale: 0.0, }; publicAPI.lookupShiftAndScale(trange, p);
const alpha = publicAPI.getAlpha(); const length = input.getNumberOfTuples(); const inIncr = input.getNumberOfComponents();
const outputV = output.getData(); const inputV = input.getData();
if (alpha >= 1.0) { if (outFormat === ScalarMappingTarget.RGBA) { for (let i = 0; i < length; i++) { const cptr = lookupFunc( inputV[i * inIncr + inputOffset], model.table, p ); outputV[i * 4] = cptr[0]; outputV[i * 4 + 1] = cptr[1]; outputV[i * 4 + 2] = cptr[2]; outputV[i * 4 + 3] = cptr[3]; } } } else { if (outFormat === ScalarMappingTarget.RGBA) { for (let i = 0; i < length; i++) { const cptr = lookupFunc( inputV[i * inIncr + inputOffset], model.table, p ); outputV[i * 4] = cptr[0]; outputV[i * 4 + 1] = cptr[1]; outputV[i * 4 + 2] = cptr[2]; outputV[i * 4 + 3] = Math.floor(cptr[3] * alpha + 0.5); } } } };
publicAPI.forceBuild = () => { let hinc = 0.0; let sinc = 0.0; let vinc = 0.0; let ainc = 0.0;
const maxIndex = model.numberOfColors - 1;
if (maxIndex) { hinc = (model.hueRange[1] - model.hueRange[0]) / maxIndex; sinc = (model.saturationRange[1] - model.saturationRange[0]) / maxIndex; vinc = (model.valueRange[1] - model.valueRange[0]) / maxIndex; ainc = (model.alphaRange[1] - model.alphaRange[0]) / maxIndex; }
model.table.length = 4 * maxIndex + 16;
const hsv = []; const rgba = []; for (let i = 0; i <= maxIndex; i++) { hsv[0] = model.hueRange[0] + i * hinc; hsv[1] = model.saturationRange[0] + i * sinc; hsv[2] = model.valueRange[0] + i * vinc;
vtkMath.hsv2rgb(hsv, rgba); rgba[3] = model.alphaRange[0] + i * ainc;
model.table[i * 4] = rgba[0] * 255.0 + 0.5; model.table[i * 4 + 1] = rgba[1] * 255.0 + 0.5; model.table[i * 4 + 2] = rgba[2] * 255.0 + 0.5; model.table[i * 4 + 3] = rgba[3] * 255.0 + 0.5; }
publicAPI.buildSpecialColors();
model.buildTime.modified(); };
publicAPI.setTable = (table) => { if (Array.isArray(table)) { const nbComponents = table[0].length; model.numberOfColors = table.length; const colorOffset = 4 - nbComponents; let offset = 0; for (let i = 0; i < model.numberOfColors; i++) { model.table[i * 4] = 255; model.table[i * 4 + 1] = 255; model.table[i * 4 + 2] = 255; model.table[i * 4 + 3] = 255; } for (let i = 0; i < table.length; i++) { const color = table[i]; for (let j = 0; j < nbComponents; j++) { model.table[offset++] = color[j]; } offset += colorOffset; } publicAPI.buildSpecialColors(); model.insertTime.modified(); publicAPI.modified(); return true; }
if (table.getNumberOfComponents() !== 4) { vtkErrorMacro('Expected 4 components for RGBA colors'); return false; } if (table.getDataType() !== VtkDataTypes.UNSIGNED_CHAR) { vtkErrorMacro('Expected unsigned char values for RGBA colors'); return false; } model.numberOfColors = table.getNumberOfTuples(); const data = table.getData(); model.table.length = data.length; for (let i = 0; i < data.length; i++) { model.table[i] = data[i]; }
publicAPI.buildSpecialColors(); model.insertTime.modified(); publicAPI.modified(); return true; };
publicAPI.buildSpecialColors = () => { const { numberOfColors } = model;
const tptr = model.table; let base = (numberOfColors + BELOW_RANGE_COLOR_INDEX) * 4;
if (model.useBelowRangeColor || numberOfColors === 0) { tptr[base] = model.belowRangeColor[0] * 255.0 + 0.5; tptr[base + 1] = model.belowRangeColor[1] * 255.0 + 0.5; tptr[base + 2] = model.belowRangeColor[2] * 255.0 + 0.5; tptr[base + 3] = model.belowRangeColor[3] * 255.0 + 0.5; } else { tptr[base] = tptr[0]; tptr[base + 1] = tptr[1]; tptr[base + 2] = tptr[2]; tptr[base + 3] = tptr[3]; }
base = (numberOfColors + ABOVE_RANGE_COLOR_INDEX) * 4; if (model.useAboveRangeColor || numberOfColors === 0) { tptr[base] = model.aboveRangeColor[0] * 255.0 + 0.5; tptr[base + 1] = model.aboveRangeColor[1] * 255.0 + 0.5; tptr[base + 2] = model.aboveRangeColor[2] * 255.0 + 0.5; tptr[base + 3] = model.aboveRangeColor[3] * 255.0 + 0.5; } else { tptr[base] = tptr[4 * (numberOfColors - 1) + 0]; tptr[base + 1] = tptr[4 * (numberOfColors - 1) + 1]; tptr[base + 2] = tptr[4 * (numberOfColors - 1) + 2]; tptr[base + 3] = tptr[4 * (numberOfColors - 1) + 3]; }
base = (numberOfColors + NAN_COLOR_INDEX) * 4; tptr[base] = model.nanColor[0] * 255.0 + 0.5; tptr[base + 1] = model.nanColor[1] * 255.0 + 0.5; tptr[base + 2] = model.nanColor[2] * 255.0 + 0.5; tptr[base + 3] = model.nanColor[3] * 255.0 + 0.5; };
publicAPI.build = () => { if ( model.table.length < 1 || (publicAPI.getMTime() > model.buildTime.getMTime() && model.insertTime.getMTime() <= model.buildTime.getMTime()) ) { publicAPI.forceBuild(); } };
if (model.table.length > 0) { publicAPI.buildSpecialColors();
model.insertTime.modified(); } }
const DEFAULT_VALUES = { numberOfColors: 256,
hueRange: [0.0, 0.66667], saturationRange: [1.0, 1.0], valueRange: [1.0, 1.0], alphaRange: [1.0, 1.0],
nanColor: [0.5, 0.0, 0.0, 1.0], belowRangeColor: [0.0, 0.0, 0.0, 1.0], aboveRangeColor: [1.0, 1.0, 1.0, 1.0], useAboveRangeColor: false, useBelowRangeColor: false,
alpha: 1.0, };
export function extend(publicAPI, model, initialValues = {}) { Object.assign(model, DEFAULT_VALUES, initialValues);
vtkScalarsToColors.extend(publicAPI, model, initialValues);
if (!model.table) { model.table = []; }
model.buildTime = {}; macro.obj(model.buildTime);
model.opaqueFlagBuildTime = {}; macro.obj(model.opaqueFlagBuildTime, { mtime: 0 });
model.insertTime = {}; macro.obj(model.insertTime, { mtime: 0 });
macro.get(publicAPI, model, ['buildTime']);
macro.setGet(publicAPI, model, [ 'numberOfColors', 'useAboveRangeColor', 'useBelowRangeColor', ]);
macro.setArray( publicAPI, model, ['alphaRange', 'hueRange', 'saturationRange', 'valueRange'], 2 );
macro.setArray( publicAPI, model, ['nanColor', 'belowRangeColor', 'aboveRangeColor'], 4 );
macro.getArray(publicAPI, model, [ 'hueRange', 'saturationRange', 'valueRange', 'alphaRange', 'nanColor', 'belowRangeColor', 'aboveRangeColor', ]);
vtkLookupTable(publicAPI, model); }
export const newInstance = macro.newInstance(extend, 'vtkLookupTable');
export default { newInstance, extend };
|