import macro from 'vtk.js/Sources/macro'; import vtkDataArray from 'vtk.js/Sources/Common/Core/DataArray'; import * as vtkMath from 'vtk.js/Sources/Common/Core/Math'; import vtkPolyData from 'vtk.js/Sources/Common/DataModel/PolyData';
const { vtkErrorMacro } = macro;
function vtkTextureMapToPlane(publicAPI, model) { model.classHierarchy.push('vtkTextureMapToPlane');
function computeNormal(output) { const VTK_TOLERANCE = 0.001;
const nbPoints = output.getPoints().getNumberOfPoints(); let dir = 0; const m = [0, 0, 0, 0, 0, 0, 0, 0, 0]; const x = [0, 0, 0]; const v = [0, 0, 0];
const bounds = output.getBounds(); const minBounds = [bounds[0], bounds[2], bounds[4]]; const maxBounds = [bounds[1], bounds[3], bounds[5]]; const length = Math.sqrt( vtkMath.distance2BetweenPoints(minBounds, maxBounds) ); let w = length; let i = 0; for (; i < 3; i++) { model.normal[i] = 0.0; if (bounds[2 * i + 1] - bounds[2 * i] < w) { dir = i; w = bounds[2 * i + 1] - bounds[2 * i]; } }
model.normal[dir] = 1.0; if (w <= length * VTK_TOLERANCE) { return; }
v[0] = 0.0; v[1] = 0.0; v[2] = 0.0; for (i = 0; i < 9; i++) { m[i] = 0.0; }
for (let ptId = 0; ptId < nbPoints; ptId++) { output.getPoints().getPoint(ptId, x);
v[0] += x[0] * x[2]; v[1] += x[1] * x[2]; v[2] += x[2];
m[0] += x[0] * x[0]; m[1] += x[0] * x[1]; m[2] += x[0];
m[3] += x[0] * x[1]; m[4] += x[1] * x[1]; m[5] += x[1];
m[6] += x[0]; m[7] += x[1]; } m[8] = nbPoints;
const c1 = [m[0], m[1], m[2]]; const c2 = [m[3], m[4], m[5]]; const c3 = [m[6], m[7], m[8]]; const matrix = [c1, c2, c3]; const det = vtkMath.determinant3x3(matrix); if (det <= VTK_TOLERANCE) { return; }
matrix[0] = v; matrix[1] = c2; matrix[2] = c3; model.normal[0] = vtkMath.determinant3x3(matrix) / det; matrix[0] = c1; matrix[1] = v; matrix[2] = c3; model.normal[1] = vtkMath.determinant3x3(matrix) / det; model.normal[2] = -1.0; }
publicAPI.requestData = (inData, outData) => { if (model.deleted) { return; } const input = inData[0]; const nbPoints = input.getPoints().getNumberOfPoints(); if (nbPoints < 3 && model.automaticPlaneGeneration) { vtkErrorMacro("Can't generate texture coordinates without points"); return; }
const output = vtkPolyData.newInstance(); output .getPoints() .setData(new Float32Array(input.getPoints().getData()), 3); output.getPolys().setData(new Uint32Array(input.getPolys().getData()));
const tcoordsData = [];
let minProj = 0; let i = 0; let j = 0; let proj = 0; const axis = [0, 0, 0]; let dir = 0; const tAxis = [0, 0, 0]; const sAxis = [0, 0, 0]; let s = 0; let t = 0; let sSf = 0; let tSf = 0; const p = [0, 0, 0];
if ( model.automaticPlaneGeneration && model.origin[0] === 0 && model.origin[1] === 0 && model.origin[2] === 0 && model.point1[0] === 0 && model.point1[1] === 0 && model.point2[0] === 0 && model.point2[1] === 0 ) { if (model.automaticPlaneGeneration) { computeNormal(output); }
vtkMath.normalize(model.normal);
minProj = 1.0; i = 0; for (; i < 3; i++) { axis[0] = 0.0; axis[1] = 0.0; axis[2] = 0.0; axis[i] = 1.0; proj = Math.abs(vtkMath.dot(model.normal, axis)); if (proj < minProj) { minProj = proj; dir = i; } } axis[0] = 0.0; axis[1] = 0.0; axis[2] = 0.0; axis[dir] = 1.0;
vtkMath.cross(model.normal, axis, tAxis); vtkMath.normalize(tAxis);
vtkMath.cross(tAxis, model.normal, sAxis);
const bounds = output.getBounds(); for (i = 0; i < 3; i++) { axis[i] = bounds[2 * i + 1] - bounds[2 * i]; }
s = vtkMath.dot(sAxis, axis); t = vtkMath.dot(tAxis, axis);
sSf = (model.sRange[1] - model.sRange[0]) / s; tSf = (model.tRange[1] - model.tRange[0]) / t; for (i = 0; i < nbPoints; i++) { output.getPoints().getPoint(i, p); for (j = 0; j < 3; j++) { axis[j] = p[j] - bounds[2 * j]; }
tcoordsData.push(model.sRange[0] + vtkMath.dot(sAxis, axis) * sSf); tcoordsData.push(model.tRange[0] + vtkMath.dot(tAxis, axis) * tSf); } } else { let num = 0;
for (i = 0; i < 3; i++) { sAxis[i] = model.point1[i] - model.origin[i]; tAxis[i] = model.point2[i] - model.origin[i]; }
let sDenom = vtkMath.dot(sAxis, sAxis); let tDenom = vtkMath.dot(tAxis, tAxis);
if (sDenom === 0.0 || tDenom === 0.0) { vtkErrorMacro('Bad plane definition'); sDenom = 1.0; tDenom = 1.0; }
for (i = 0; i < nbPoints; i++) { output.getPoints().getPoint(i, p); for (j = 0; j < 3; j++) { axis[j] = p[j] - model.origin[j]; }
num = sAxis[0] * axis[0] + sAxis[1] * axis[1] + sAxis[2] * axis[2]; tcoordsData.push(num / sDenom);
num = tAxis[0] * axis[0] + tAxis[1] * axis[1] + tAxis[2] * axis[2]; tcoordsData.push(num / tDenom); } }
const tCoords = vtkDataArray.newInstance({ name: 'Texture Coordinates', numberOfComponents: 2, size: nbPoints, values: tcoordsData, });
output.getPointData().setTCoords(tCoords);
outData[0] = output; }; }
const DEFAULT_VALUES = { origin: [0, 0, 0], point1: [0, 0, 0], point2: [0, 0, 0], normal: [0, 0, 0], sRange: [0, 1], tRange: [0, 1], automaticPlaneGeneration: 1, };
export function extend(publicAPI, model, initialValues = {}) { Object.assign(model, DEFAULT_VALUES, initialValues);
macro.obj(publicAPI, model);
macro.setGetArray( publicAPI, model, ['origin', 'point1', 'point2', 'normal', 'sRange', 'tRange'], 3 ); macro.setGet(publicAPI, model, ['automaticPlaneGeneration']);
macro.algo(publicAPI, model, 1, 1); vtkTextureMapToPlane(publicAPI, model); }
export const newInstance = macro.newInstance(extend, 'vtkTextureMapToPlane');
export default { newInstance, extend };
|