DataSetAttributes

Source

Constants.js
export const AttributeTypes = {
SCALARS: 0,
VECTORS: 1,
NORMALS: 2,
TCOORDS: 3,
TENSORS: 4,
GLOBALIDS: 5,
PEDIGREEIDS: 6,
EDGEFLAG: 7,
NUM_ATTRIBUTES: 8,
};

export const AttributeLimitTypes = {
MAX: 0,
EXACT: 1,
NOLIMIT: 2,
};

export const CellGhostTypes = {
DUPLICATECELL: 1, // the cell is present on multiple processors
HIGHCONNECTIVITYCELL: 2, // the cell has more neighbors than in a regular mesh
LOWCONNECTIVITYCELL: 4, // the cell has less neighbors than in a regular mesh
REFINEDCELL: 8, // other cells are present that refines it.
EXTERIORCELL: 16, // the cell is on the exterior of the data set
HIDDENCELL: 32, // the cell is needed to maintain connectivity, but the data values should be ignored.
};

export const PointGhostTypes = {
DUPLICATEPOINT: 1, // the cell is present on multiple processors
HIDDENPOINT: 2, // the point is needed to maintain connectivity, but the data values should be ignored.
};

export const AttributeCopyOperations = {
COPYTUPLE: 0,
INTERPOLATE: 1,
PASSDATA: 2,
ALLCOPY: 3, // all of the above
};

export const ghostArrayName = 'vtkGhostType';

export const DesiredOutputPrecision = {
DEFAULT: 0, // use the point type that does not truncate any data
SINGLE: 1, // use Float32Array
DOUBLE: 2, // use Float64Array
};

export default {
AttributeCopyOperations,
AttributeLimitTypes,
AttributeTypes,
CellGhostTypes,
DesiredOutputPrecision,
PointGhostTypes,
ghostArrayName,
};
FieldData.js
import vtk from 'vtk.js/Sources/vtk';
import macro from 'vtk.js/Sources/macro';
import vtkDataArray from 'vtk.js/Sources/Common/Core/DataArray';

// ----------------------------------------------------------------------------
// vtkFieldData methods
// ----------------------------------------------------------------------------

function vtkFieldData(publicAPI, model) {
model.classHierarchy.push('vtkFieldData');
const superGetState = publicAPI.getState;

// Decode serialized data if any
if (model.arrays) {
model.arrays = model.arrays.map((item) => ({ data: vtk(item.data) }));
}

publicAPI.initialize = () => {
publicAPI.initializeFields();
publicAPI.copyAllOn();
publicAPI.clearFieldFlags();
};

publicAPI.initializeFields = () => {
model.arrays = [];
model.copyFieldFlags = {};
publicAPI.modified();
};

publicAPI.copyStructure = (other) => {
publicAPI.initializeFields();
model.copyFieldFlags = other.getCopyFieldFlags().map((x) => x); // Deep-copy
model.arrays = other.arrays().map((x) => ({ array: x })); // Deep-copy
// TODO: Copy array information objects (once we support information objects)
};

publicAPI.getNumberOfArrays = () => model.arrays.length;
publicAPI.getNumberOfActiveArrays = () => model.arrays.length;
publicAPI.addArray = (arr) => {
model.arrays = [].concat(model.arrays, { data: arr });
return model.arrays.length - 1;
};
publicAPI.removeAllArrays = () => {
model.arrays = [];
};
publicAPI.removeArray = (arrayName) => {
model.arrays = model.arrays.filter(
(entry) => arrayName !== entry.data.getName()
);
};
publicAPI.removeArrayByIndex = (arrayIdx) => {
model.arrays = model.arrays.filter((entry, idx) => idx !== arrayIdx);
};
publicAPI.getArrays = () => model.arrays.map((entry) => entry.data);
publicAPI.getArray = (arraySpec) =>
typeof arraySpec === 'number'
? publicAPI.getArrayByIndex(arraySpec)
: publicAPI.getArrayByName(arraySpec);
publicAPI.getArrayByName = (arrayName) =>
model.arrays.reduce(
(a, b, i) => (b.data.getName() === arrayName ? b.data : a),
null
);
publicAPI.getArrayWithIndex = (arrayName) =>
model.arrays.reduce(
(a, b, i) =>
b.data && b.data.getName() === arrayName
? { array: b.data, index: i }
: a,
{ array: null, index: -1 }
);
publicAPI.getArrayByIndex = (idx) =>
idx >= 0 && idx < model.arrays.length ? model.arrays[idx].data : null;
publicAPI.hasArray = (arrayName) =>
publicAPI.getArrayWithIndex(arrayName).index >= 0;
publicAPI.getArrayName = (idx) => {
const arr = model.arrays[idx];
return arr ? arr.data.getName() : '';
};
publicAPI.getCopyFieldFlags = () => model.copyFieldFlags;
publicAPI.getFlag = (arrayName) => model.copyFieldFlags[arrayName];
publicAPI.passData = (other, fromId = -1, toId = -1) => {
other.getArrays().forEach((arr) => {
const copyFlag = publicAPI.getFlag(arr.getName());
if (
copyFlag !== false &&
!(model.doCopyAllOff && copyFlag !== true) &&
arr
) {
let destArr = publicAPI.getArrayByName(arr.getName());
if (!destArr) {
if (fromId < 0 || fromId > arr.getNumberOfTuples()) {
publicAPI.addArray(arr);
} else {
const ncomps = arr.getNumberOfComponents();
let newSize = arr.getNumberOfValues();
const tId = toId > -1 ? toId : fromId;
if (newSize < tId * ncomps) {
newSize = (tId + 1) * ncomps;
}
destArr = vtkDataArray.newInstance({
name: arr.getName(),
dataType: arr.getDataType(),
numberOfComponents: arr.getNumberOfComponents(),
size: newSize,
});
destArr.setTuple(tId, arr.getTuple(fromId));
publicAPI.addArray(destArr);
}
} else if (
arr.getNumberOfComponents() === destArr.getNumberOfComponents()
) {
if (fromId > -1 && fromId < arr.getNumberOfTuples()) {
const tId = toId > -1 ? toId : fromId;
destArr.setTuple(tId, arr.getTuple(fromId));
} else {
// if fromId and not provided, just copy all (or as much possible)
// of arr to destArr.
for (let i = 0; i < arr.getNumberOfTuples(); ++i) {
destArr.setTuple(i, arr.getTuple(i));
}
}
}
}
});
};
publicAPI.copyFieldOn = (arrayName) => {
model.copyFieldFlags[arrayName] = true;
};
publicAPI.copyFieldOff = (arrayName) => {
model.copyFieldFlags[arrayName] = false;
};
publicAPI.copyAllOn = () => {
if (!model.doCopyAllOn || model.doCopyAllOff) {
model.doCopyAllOn = true;
model.doCopyAllOff = false;
publicAPI.modified();
}
};
publicAPI.copyAllOff = () => {
if (model.doCopyAllOn || !model.doCopyAllOff) {
model.doCopyAllOn = false;
model.doCopyAllOff = true;
publicAPI.modified();
}
};
publicAPI.clearFieldFlags = () => {
model.copyFieldFlags = {};
};
publicAPI.deepCopy = (other) => {
model.arrays = other.getArrays().map((arr) => {
const arrNew = arr.newClone();
arrNew.deepCopy(arr);
return { data: arrNew };
});
};
publicAPI.copyFlags = (other) => other.getCopyFieldFlags().map((x) => x);
// TODO: publicAPI.squeeze = () => model.arrays.forEach(entry => entry.data.squeeze());
publicAPI.reset = () => model.arrays.forEach((entry) => entry.data.reset());
// TODO: getActualMemorySize
publicAPI.getMTime = () =>
model.arrays.reduce(
(a, b) => (b.data.getMTime() > a ? b.data.getMTime() : a),
model.mtime
);
// TODO: publicAPI.getField = (ids, other) => { copy ids from other into this model's arrays }
// TODO: publicAPI.getArrayContainingComponent = (component) => ...
publicAPI.getNumberOfComponents = () =>
model.arrays.reduce((a, b) => a + b.data.getNumberOfComponents(), 0);
publicAPI.getNumberOfTuples = () =>
model.arrays.length > 0 ? model.arrays[0].getNumberOfTuples() : 0;

publicAPI.getState = () => {
const result = superGetState();
result.arrays = model.arrays.map((item) => ({
data: item.data.getState(),
}));
return result;
};
}

const DEFAULT_VALUES = {
arrays: [],
copyFieldFlags: [], // fields not to copy
doCopyAllOn: true,
doCopyAllOff: false,
};

export function extend(publicAPI, model, initialValues = {}) {
Object.assign(model, DEFAULT_VALUES, initialValues);

macro.obj(publicAPI, model);

vtkFieldData(publicAPI, model);
}

// ----------------------------------------------------------------------------

export const newInstance = macro.newInstance(extend, 'vtkFieldData');

// ----------------------------------------------------------------------------

export default { newInstance, extend };
index.js
import macro from 'vtk.js/Sources/macro';
import vtkFieldData from 'vtk.js/Sources/Common/DataModel/DataSetAttributes/FieldData';
import Constants from 'vtk.js/Sources/Common/DataModel/DataSetAttributes/Constants';
import vtkDataArray from 'vtk.js/Sources/Common/Core/DataArray';

const { AttributeTypes, AttributeCopyOperations } = Constants;
const { vtkWarningMacro } = macro;

// ----------------------------------------------------------------------------
// vtkDataSetAttributes methods
// ----------------------------------------------------------------------------

function vtkDataSetAttributes(publicAPI, model) {
const attrTypes = [
'Scalars',
'Vectors',
'Normals',
'TCoords',
'Tensors',
'GlobalIds',
'PedigreeIds',
];

function cleanAttributeType(attType) {
// Given an integer or string, convert the result to one of the
// strings in the "attrTypes" array above or null (if
// no match is found)
let cleanAttType = attrTypes.find(
(ee) =>
AttributeTypes[ee.toUpperCase()] === attType ||
(typeof attType !== 'number' &&
ee.toLowerCase() === attType.toLowerCase())
);
if (typeof cleanAttType === 'undefined') {
cleanAttType = null;
}
return cleanAttType;
}

// Set our className
model.classHierarchy.push('vtkDataSetAttributes');

publicAPI.checkNumberOfComponents = (x) => true; // TODO

publicAPI.setAttribute = (arr, uncleanAttType) => {
const attType = cleanAttributeType(uncleanAttType);
if (
arr &&
attType.toUpperCase() === 'PEDIGREEIDS' &&
!arr.isA('vtkDataArray')
) {
vtkWarningMacro(
`Cannot set attribute ${attType}. The attribute must be a vtkDataArray.`
);
return -1;
}
if (arr && !publicAPI.checkNumberOfComponents(arr, attType)) {
vtkWarningMacro(
`Cannot set attribute ${attType}. Incorrect number of components.`
);
return -1;
}
let currentAttribute = model[`active${attType}`];
if (currentAttribute >= 0 && currentAttribute < model.arrays.length) {
if (model.arrays[currentAttribute] === arr) {
return currentAttribute;
}
publicAPI.removeArrayByIndex(currentAttribute);
}

if (arr) {
currentAttribute = publicAPI.addArray(arr);
model[`active${attType}`] = currentAttribute;
} else {
model[`active${attType}`] = -1;
}
publicAPI.modified();
return model[`active${attType}`];
};

publicAPI.setActiveAttributeByName = (arrayName, attType) =>
publicAPI.setActiveAttributeByIndex(
publicAPI.getArrayWithIndex(arrayName).index,
attType
);

publicAPI.setActiveAttributeByIndex = (arrayIdx, uncleanAttType) => {
const attType = cleanAttributeType(uncleanAttType);
if (arrayIdx >= 0 && arrayIdx < model.arrays.length) {
if (attType.toUpperCase() !== 'PEDIGREEIDS') {
const arr = publicAPI.getArrayByIndex(arrayIdx);
if (!arr.isA('vtkDataArray')) {
vtkWarningMacro(
`Cannot set attribute ${attType}. Only vtkDataArray subclasses can be set as active attributes.`
);
return -1;
}
if (!publicAPI.checkNumberOfComponents(arr, attType)) {
vtkWarningMacro(
`Cannot set attribute ${attType}. Incorrect number of components.`
);
return -1;
}
}
model[`active${attType}`] = arrayIdx;
publicAPI.modified();
return arrayIdx;
}

if (arrayIdx === -1) {
model[`active${attType}`] = arrayIdx;
publicAPI.modified();
}

return -1;
};

publicAPI.getActiveAttribute = (attType) => {
// Given an integer enum value or a string (with random capitalization),
// find the matching string in attrTypes.
const cleanAttType = cleanAttributeType(attType);
return publicAPI[`get${cleanAttType}`]();
};

// Override to allow proper handling of active attributes
publicAPI.removeAllArrays = () => {
model.arrays = [];
attrTypes.forEach((attType) => {
model[`active${attType}`] = -1;
});
};

// Override to allow proper handling of active attributes
publicAPI.removeArray = (arrayName) => {
model.arrays = model.arrays.filter((entry, idx) => {
if (arrayName === entry.data.getName()) {
// Found the array to remove, but is it an active attribute?
attrTypes.forEach((attType) => {
if (idx === model[`active${attType}`]) {
model[`active${attType}`] = -1;
}
});
return false;
}
return true;
});
};

// Override to allow proper handling of active attributes
publicAPI.removeArrayByIndex = (arrayIdx) => {
model.arrays = model.arrays.filter((entry, idx) => idx !== arrayIdx);
attrTypes.forEach((attType) => {
if (arrayIdx === model[`active${attType}`]) {
model[`active${attType}`] = -1;
}
});
};

attrTypes.forEach((value) => {
const activeVal = `active${value}`;
publicAPI[`get${value}`] = () =>
publicAPI.getArrayByIndex(model[activeVal]);
publicAPI[`set${value}`] = (da) => publicAPI.setAttribute(da, value);
publicAPI[`setActive${value}`] = (arrayName) =>
publicAPI.setActiveAttributeByIndex(
publicAPI.getArrayWithIndex(arrayName).index,
value
);
publicAPI[`copy${value}Off`] = () => {
publicAPI.initialize();
const attType = value.toUpperCase();
model.copyAttributeFlags[AttributeCopyOperations.PASSDATA][
AttributeTypes[attType]
] = false;
};
});

publicAPI.initialize = macro.chain(publicAPI.initialize, () => {
// Default to copying all attributes in every circumstance:
model.copyAttributeFlags = [];
Object.keys(AttributeCopyOperations)
.filter((op) => op !== 'ALLCOPY')
.forEach((attCopyOp) => {
model.copyAttributeFlags[
AttributeCopyOperations[attCopyOp]
] = Object.keys(AttributeTypes)
.filter((ty) => ty !== 'NUM_ATTRIBUTES')
.reduce((a, b) => {
a[AttributeTypes[b]] = true;
return a;
}, []);
});
// Override some operations where we don't want to copy:
model.copyAttributeFlags[AttributeCopyOperations.COPYTUPLE][
AttributeTypes.GLOBALIDS
] = false;
model.copyAttributeFlags[AttributeCopyOperations.INTERPOLATE][
AttributeTypes.GLOBALIDS
] = false;
model.copyAttributeFlags[AttributeCopyOperations.COPYTUPLE][
AttributeTypes.PEDIGREEIDS
] = false;
});

// Process dataArrays if any
if (model.dataArrays && Object.keys(model.dataArrays).length) {
Object.keys(model.dataArrays).forEach((name) => {
if (
!model.dataArrays[name].ref &&
model.dataArrays[name].type === 'vtkDataArray'
) {
publicAPI.addArray(vtkDataArray.newInstance(model.dataArrays[name]));
}
});
}

const superShallowCopy = publicAPI.shallowCopy;
publicAPI.shallowCopy = (other, debug) => {
superShallowCopy(other, debug);
model.arrays = other.getArrays().map((arr) => {
const arrNew = arr.newClone();
arrNew.shallowCopy(arr, debug);
return { data: arrNew };
});
};
}

// ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------

const DEFAULT_VALUES = {
activeScalars: -1,
activeVectors: -1,
activeTensors: -1,
activeNormals: -1,
activeTCoords: -1,
activeGlobalIds: -1,
activePedigreeIds: -1,
};

// ----------------------------------------------------------------------------

export function extend(publicAPI, model, initialValues = {}) {
Object.assign(model, DEFAULT_VALUES, initialValues);

// Object methods
vtkFieldData.extend(publicAPI, model, initialValues);
macro.setGet(publicAPI, model, [
'activeScalars',
'activeNormals',
'activeTCoords',
'activeVectors',
'activeTensors',
'activeGlobalIds',
'activePedigreeIds',
]);

if (!model.arrays) {
model.arrays = {};
}

// Object specific methods
vtkDataSetAttributes(publicAPI, model);
}

// ----------------------------------------------------------------------------

export const newInstance = macro.newInstance(extend, 'vtkDataSetAttributes');

// ----------------------------------------------------------------------------

export default Object.assign({ newInstance, extend }, Constants);