@thewtex/vtk.js-esm
Version:
Visualization Toolkit for the Web
516 lines (411 loc) • 19.3 kB
JavaScript
import _defineProperty from '@babel/runtime/helpers/defineProperty';
import macro from '../../macro.js';
import vtkAbstractMapper3D from './AbstractMapper3D.js';
import vtkDataArray from '../../Common/Core/DataArray.js';
import vtkImageData from '../../Common/DataModel/ImageData.js';
import vtkLookupTable from '../../Common/Core/LookupTable.js';
import { M as createUninitializedBounds, i as isNan } from '../../Common/Core/Math/index.js';
import vtkScalarsToColors from '../../Common/Core/ScalarsToColors/Constants.js';
import CoincidentTopologyHelper from './Mapper/CoincidentTopologyHelper.js';
import Constants from './Mapper/Constants.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 staticOffsetAPI = CoincidentTopologyHelper.staticOffsetAPI,
otherStaticMethods = CoincidentTopologyHelper.otherStaticMethods;
var ColorMode = Constants.ColorMode,
ScalarMode = Constants.ScalarMode,
GetArray = Constants.GetArray;
var VectorMode = vtkScalarsToColors.VectorMode;
var VtkDataTypes = vtkDataArray.VtkDataTypes; // ----------------------------------------------------------------------------
function notImplemented(method) {
return function () {
return macro.vtkErrorMacro("vtkMapper::".concat(method, " - NOT IMPLEMENTED"));
};
} // ----------------------------------------------------------------------------
// vtkMapper methods
// ----------------------------------------------------------------------------
function vtkMapper(publicAPI, model) {
// Set our className
model.classHierarchy.push('vtkMapper');
publicAPI.getBounds = function () {
var input = publicAPI.getInputData();
if (!input) {
model.bounds = createUninitializedBounds();
} else {
if (!model.static) {
publicAPI.update();
}
model.bounds = input.getBounds();
}
return model.bounds;
};
publicAPI.setForceCompileOnly = function (v) {
model.forceCompileOnly = v; // make sure we do NOT call modified()
};
publicAPI.createDefaultLookupTable = function () {
model.lookupTable = vtkLookupTable.newInstance();
};
publicAPI.getColorModeAsString = function () {
return macro.enumToString(ColorMode, model.colorMode);
};
publicAPI.setColorModeToDefault = function () {
return publicAPI.setColorMode(0);
};
publicAPI.setColorModeToMapScalars = function () {
return publicAPI.setColorMode(1);
};
publicAPI.setColorModeToDirectScalars = function () {
return publicAPI.setColorMode(2);
};
publicAPI.getScalarModeAsString = function () {
return macro.enumToString(ScalarMode, model.scalarMode);
};
publicAPI.setScalarModeToDefault = function () {
return publicAPI.setScalarMode(0);
};
publicAPI.setScalarModeToUsePointData = function () {
return publicAPI.setScalarMode(1);
};
publicAPI.setScalarModeToUseCellData = function () {
return publicAPI.setScalarMode(2);
};
publicAPI.setScalarModeToUsePointFieldData = function () {
return publicAPI.setScalarMode(3);
};
publicAPI.setScalarModeToUseCellFieldData = function () {
return publicAPI.setScalarMode(4);
};
publicAPI.setScalarModeToUseFieldData = function () {
return publicAPI.setScalarMode(5);
};
publicAPI.getAbstractScalars = function (input, scalarMode, arrayAccessMode, arrayId, arrayName) {
// make sure we have an input
if (!input || !model.scalarVisibility) {
return {
scalars: null,
cellFLag: false
};
}
var scalars = null;
var cellFlag = false; // get and scalar data according to scalar mode
if (scalarMode === ScalarMode.DEFAULT) {
scalars = input.getPointData().getScalars();
if (!scalars) {
scalars = input.getCellData().getScalars();
cellFlag = true;
}
} else if (scalarMode === ScalarMode.USE_POINT_DATA) {
scalars = input.getPointData().getScalars();
} else if (scalarMode === ScalarMode.USE_CELL_DATA) {
scalars = input.getCellData().getScalars();
cellFlag = true;
} else if (scalarMode === ScalarMode.USE_POINT_FIELD_DATA) {
var pd = input.getPointData();
if (arrayAccessMode === GetArray.BY_ID) {
scalars = pd.getArrayByIndex(arrayId);
} else {
scalars = pd.getArrayByName(arrayName);
}
} else if (scalarMode === ScalarMode.USE_CELL_FIELD_DATA) {
var cd = input.getCellData();
cellFlag = true;
if (arrayAccessMode === GetArray.BY_ID) {
scalars = cd.getArrayByIndex(arrayId);
} else {
scalars = cd.getArrayByName(arrayName);
}
} else if (scalarMode === ScalarMode.USE_FIELD_DATA) {
var fd = input.getFieldData();
if (arrayAccessMode === GetArray.BY_ID) {
scalars = fd.getArrayByIndex(arrayId);
} else {
scalars = fd.getArrayByName(arrayName);
}
}
return {
scalars: scalars,
cellFlag: cellFlag
};
};
publicAPI.mapScalars = function (input, alpha) {
var scalars = publicAPI.getAbstractScalars(input, model.scalarMode, model.arrayAccessMode, model.arrayId, model.colorByArrayName).scalars;
if (!scalars) {
model.colorCoordinates = null;
model.colorTextureMap = null;
model.colorMapColors = null;
return;
} // we want to only recompute when something has changed
var toString = "".concat(publicAPI.getMTime()).concat(scalars.getMTime()).concat(alpha);
if (model.colorBuildString === toString) return;
if (!model.useLookupTableScalarRange) {
publicAPI.getLookupTable().setRange(model.scalarRange[0], model.scalarRange[1]);
} // Decide between texture color or vertex color.
// Cell data always uses vertex color.
// Only point data can use both texture and vertex coloring.
if (publicAPI.canUseTextureMapForColoring(input)) {
publicAPI.mapScalarsToTexture(scalars, alpha);
} else {
model.colorCoordinates = null;
model.colorTextureMap = null;
var lut = publicAPI.getLookupTable();
if (lut) {
// Ensure that the lookup table is built
lut.build();
model.colorMapColors = lut.mapScalars(scalars, model.colorMode, -1);
}
}
model.colorBuildString = "".concat(publicAPI.getMTime()).concat(scalars.getMTime()).concat(alpha);
}; //-----------------------------------------------------------------------------
publicAPI.scalarToTextureCoordinate = function (scalarValue, // Input scalar
rangeMin, // range[0]
invRangeWidth) {
// 1/(range[1]-range[0])
var texCoordS = 0.5; // Scalar value is arbitrary when NaN
var texCoordT = 1.0; // 1.0 in t coordinate means NaN
if (!isNan(scalarValue)) {
// 0.0 in t coordinate means not NaN. So why am I setting it to 0.49?
// Because when you are mapping scalars and you have a NaN adjacent to
// anything else, the interpolation everywhere should be NaN. Thus, I
// want the NaN color everywhere except right on the non-NaN neighbors.
// To simulate this, I set the t coord for the real numbers close to
// the threshold so that the interpolation almost immediately looks up
// the NaN value.
texCoordT = 0.49;
texCoordS = (scalarValue - rangeMin) * invRangeWidth; // Some implementations apparently don't handle relatively large
// numbers (compared to the range [0.0, 1.0]) very well. In fact,
// values above 1122.0f appear to cause texture wrap-around on
// some systems even when edge clamping is enabled. Why 1122.0f? I
// don't know. For safety, we'll clamp at +/- 1000. This will
// result in incorrect images when the texture value should be
// above or below 1000, but I don't have a better solution.
if (texCoordS > 1000.0) {
texCoordS = 1000.0;
} else if (texCoordS < -1000.0) {
texCoordS = -1000.0;
}
}
return {
texCoordS: texCoordS,
texCoordT: texCoordT
};
}; //-----------------------------------------------------------------------------
publicAPI.createColorTextureCoordinates = function (input, output, numScalars, numComps, component, range, tableRange, tableNumberOfColors, useLogScale) {
// We have to change the range used for computing texture
// coordinates slightly to accommodate the special above- and
// below-range colors that are the first and last texels,
// respectively.
var scalarTexelWidth = (range[1] - range[0]) / tableNumberOfColors;
var paddedRange = [];
paddedRange[0] = range[0] - scalarTexelWidth;
paddedRange[1] = range[1] + scalarTexelWidth;
var invRangeWidth = 1.0 / (paddedRange[1] - paddedRange[0]);
var outputV = output.getData();
var inputV = input.getData();
var count = 0;
var outputCount = 0;
if (component < 0 || component >= numComps) {
for (var scalarIdx = 0; scalarIdx < numScalars; ++scalarIdx) {
var sum = 0;
for (var compIdx = 0; compIdx < numComps; ++compIdx) {
sum += inputV[count] * inputV[count];
count++;
}
var magnitude = Math.sqrt(sum);
if (useLogScale) {
magnitude = vtkLookupTable.applyLogScale(magnitude, tableRange, range);
}
var outputs = publicAPI.scalarToTextureCoordinate(magnitude, paddedRange[0], invRangeWidth);
outputV[outputCount] = outputs.texCoordS;
outputV[outputCount + 1] = outputs.texCoordT;
outputCount += 2;
}
} else {
count += component;
for (var _scalarIdx = 0; _scalarIdx < numScalars; ++_scalarIdx) {
var inputValue = inputV[count];
if (useLogScale) {
inputValue = vtkLookupTable.applyLogScale(inputValue, tableRange, range);
}
var _outputs = publicAPI.scalarToTextureCoordinate(inputValue, paddedRange[0], invRangeWidth);
outputV[outputCount] = _outputs.texCoordS;
outputV[outputCount + 1] = _outputs.texCoordT;
outputCount += 2;
count += numComps;
}
}
};
publicAPI.mapScalarsToTexture = function (scalars, alpha) {
var range = model.lookupTable.getRange();
var useLogScale = model.lookupTable.usingLogScale();
if (useLogScale) {
// convert range to log.
vtkLookupTable.getLogRange(range, range);
}
var origAlpha = model.lookupTable.getAlpha(); // Get rid of vertex color array. Only texture or vertex coloring
// can be active at one time. The existence of the array is the
// signal to use that technique.
model.colorMapColors = null; // If the lookup table has changed, then recreate the color texture map.
// Set a new lookup table changes this->MTime.
if (model.colorTextureMap == null || publicAPI.getMTime() > model.colorTextureMap.getMTime() || model.lookupTable.getMTime() > model.colorTextureMap.getMTime() || model.lookupTable.getAlpha() !== alpha) {
model.lookupTable.setAlpha(alpha);
model.colorTextureMap = null; // Get the texture map from the lookup table.
// Create a dummy ramp of scalars.
// In the future, we could extend vtkScalarsToColors.
model.lookupTable.build();
var numberOfColors = model.lookupTable.getNumberOfAvailableColors();
if (numberOfColors > 4094) {
numberOfColors = 4094;
}
numberOfColors += 2;
var k = (range[1] - range[0]) / (numberOfColors - 1 - 2);
var newArray = new Float64Array(numberOfColors * 2);
for (var i = 0; i < numberOfColors; ++i) {
newArray[i] = range[0] + i * k - k; // minus k to start at below range color
if (useLogScale) {
newArray[i] = Math.pow(10.0, newArray[i]);
}
} // Dimension on NaN.
for (var _i = 0; _i < numberOfColors; ++_i) {
newArray[_i + numberOfColors] = NaN;
}
model.colorTextureMap = vtkImageData.newInstance();
model.colorTextureMap.setExtent(0, numberOfColors - 1, 0, 1, 0, 0);
var tmp = vtkDataArray.newInstance({
numberOfComponents: 1,
values: newArray
});
model.colorTextureMap.getPointData().setScalars(model.lookupTable.mapScalars(tmp, model.colorMode, 0));
model.lookupTable.setAlpha(origAlpha);
} // Create new coordinates if necessary.
// Need to compare lookup table in case the range has changed.
if (!model.colorCoordinates || publicAPI.getMTime() > model.colorCoordinates.getMTime() || publicAPI.getInputData(0).getMTime() > model.colorCoordinates.getMTime() || model.lookupTable.getMTime() > model.colorCoordinates.getMTime()) {
// Get rid of old colors
model.colorCoordinates = null; // Now create the color texture coordinates.
var numComps = scalars.getNumberOfComponents();
var num = scalars.getNumberOfTuples(); // const fArray = new FloatArray(num * 2);
model.colorCoordinates = vtkDataArray.newInstance({
numberOfComponents: 2,
values: new Float32Array(num * 2)
});
var scalarComponent = model.lookupTable.getVectorComponent(); // Although I like the feature of applying magnitude to single component
// scalars, it is not how the old MapScalars for vertex coloring works.
if (model.lookupTable.getVectorMode() === VectorMode.MAGNITUDE && scalars.getNumberOfComponents() > 1) {
scalarComponent = -1;
}
publicAPI.createColorTextureCoordinates(scalars, model.colorCoordinates, num, numComps, scalarComponent, range, model.lookupTable.getRange(), model.colorTextureMap.getPointData().getScalars().getNumberOfTuples() / 2 - 2, useLogScale);
}
};
publicAPI.getIsOpaque = function () {
var lut = publicAPI.getLookupTable();
if (lut) {
// Ensure that the lookup table is built
lut.build();
return lut.isOpaque();
}
return true;
};
publicAPI.canUseTextureMapForColoring = function (input) {
if (!model.interpolateScalarsBeforeMapping) {
return false; // user doesn't want us to use texture maps at all.
} // index color does not use textures
if (model.lookupTable && model.lookupTable.getIndexedLookup()) {
return false;
}
var gasResult = publicAPI.getAbstractScalars(input, model.scalarMode, model.arrayAccessMode, model.arrayId, model.colorByArrayName);
var scalars = gasResult.scalars;
if (!scalars) {
// no scalars on this dataset, we don't care if texture is used at all.
return false;
}
if (gasResult.cellFlag) {
return false; // cell data colors, don't use textures.
}
if (model.colorMode === ColorMode.DEFAULT && scalars.getDataType() === VtkDataTypes.UNSIGNED_CHAR || model.colorMode === ColorMode.DIRECT_SCALARS) {
// Don't use texture is direct coloring using RGB unsigned chars is
// requested.
return false;
}
return true;
};
publicAPI.clearColorArrays = function () {
model.colorMapColors = null;
model.colorCoordinates = null;
model.colorTextureMap = null;
};
publicAPI.getLookupTable = function () {
if (!model.lookupTable) {
publicAPI.createDefaultLookupTable();
}
return model.lookupTable;
};
publicAPI.getMTime = function () {
var mt = model.mtime;
if (model.lookupTable !== null) {
var time = model.lookupTable.getMTime();
mt = time > mt ? time : mt;
}
return mt;
};
publicAPI.getPrimitiveCount = function () {
var input = publicAPI.getInputData();
var pcount = {
points: input.getPoints().getNumberOfValues() / 3,
verts: input.getVerts().getNumberOfValues() - input.getVerts().getNumberOfCells(),
lines: input.getLines().getNumberOfValues() - 2 * input.getLines().getNumberOfCells(),
triangles: input.getPolys().getNumberOfValues() - 3 * input.getLines().getNumberOfCells()
};
return pcount;
};
publicAPI.acquireInvertibleLookupTable = notImplemented('AcquireInvertibleLookupTable');
publicAPI.valueToColor = notImplemented('ValueToColor');
publicAPI.colorToValue = notImplemented('ColorToValue');
publicAPI.useInvertibleColorFor = notImplemented('UseInvertibleColorFor');
publicAPI.clearInvertibleColor = notImplemented('ClearInvertibleColor');
} // ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------
var DEFAULT_VALUES = {
colorMapColors: null,
// Same as this->Colors
static: false,
lookupTable: null,
scalarVisibility: true,
scalarRange: [0, 1],
useLookupTableScalarRange: false,
colorMode: 0,
scalarMode: 0,
arrayAccessMode: 1,
// By_NAME
renderTime: 0,
colorByArrayName: null,
fieldDataTupleId: -1,
interpolateScalarsBeforeMapping: false,
colorCoordinates: null,
colorTextureMap: null,
forceCompileOnly: 0,
useInvertibleColors: false,
invertibleScalars: null,
viewSpecificProperties: null,
customShaderAttributes: []
}; // ----------------------------------------------------------------------------
function extend(publicAPI, model) {
var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
Object.assign(model, DEFAULT_VALUES, initialValues); // Inheritance
vtkAbstractMapper3D.extend(publicAPI, model, initialValues);
macro.get(publicAPI, model, ['colorCoordinates', 'colorMapColors', 'colorTextureMap']);
macro.setGet(publicAPI, model, ['colorByArrayName', 'arrayAccessMode', 'colorMode', 'fieldDataTupleId', 'interpolateScalarsBeforeMapping', 'lookupTable', 'renderTime', 'scalarMode', 'scalarVisibility', 'static', 'useLookupTableScalarRange', 'viewSpecificProperties', 'customShaderAttributes' // point data array names that will be transferred to the VBO
]);
macro.setGetArray(publicAPI, model, ['scalarRange'], 2);
if (!model.viewSpecificProperties) {
model.viewSpecificProperties = {};
}
CoincidentTopologyHelper.implementCoincidentTopologyMethods(publicAPI, model); // Object methods
vtkMapper(publicAPI, model);
} // ----------------------------------------------------------------------------
var newInstance = macro.newInstance(extend, 'vtkMapper'); // ----------------------------------------------------------------------------
var vtkMapper$1 = _objectSpread(_objectSpread(_objectSpread({
newInstance: newInstance,
extend: extend
}, staticOffsetAPI), otherStaticMethods), Constants);
export default vtkMapper$1;
export { extend, newInstance };