@kitware/vtk.js
Version:
Visualization Toolkit for the Web
159 lines (142 loc) • 5.91 kB
JavaScript
import { m as macro } from '../../macros2.js';
import vtkCellArray from '../../Common/Core/CellArray.js';
import vtkDataArray from '../../Common/Core/DataArray.js';
import { b as vtkMath } from '../../Common/Core/Math/index.js';
import vtkPoints from '../../Common/Core/Points.js';
import vtkPolyData from '../../Common/DataModel/PolyData.js';
import { DesiredOutputPrecision } from '../../Common/DataModel/DataSetAttributes/Constants.js';
const {
vtkErrorMacro
} = macro;
const {
VtkDataTypes
} = vtkDataArray;
// ----------------------------------------------------------------------------
// vtkEllipseArcSource methods
// ----------------------------------------------------------------------------
function vtkEllipseArcSource(publicAPI, model) {
// Set our className
model.classHierarchy.push('vtkEllipseArcSource');
publicAPI.requestData = (inData, outData) => {
const isClosedShape = Math.abs(model.segmentAngle - 360.0) < 1e-5;
const resolution = model.close && !isClosedShape ? model.resolution + 1 : model.resolution;
const numLines = resolution;
const numPts = resolution + 1;
const tc = [0.0, 0.0];
const output = outData[0]?.initialize() || vtkPolyData.newInstance();
// Make sure the normal vector is normalized
const normal = [...model.normal];
vtkMath.normalize(normal);
// Get orthogonal vector between user-defined major radius and normal
const orthogonalVect = [0, 0, 0];
vtkMath.cross(normal, model.majorRadiusVector, orthogonalVect);
if (vtkMath.norm(orthogonalVect) < 1e-10) {
vtkErrorMacro('Ellipse normal vector and major radius axis are collinear');
return;
}
vtkMath.normalize(orthogonalVect);
const majorRadiusVect = [0, 0, 0];
vtkMath.cross(orthogonalVect, normal, majorRadiusVect);
vtkMath.normalize(majorRadiusVect);
const a = vtkMath.norm(model.majorRadiusVector);
const b = a * model.ratio;
let startAngleRad = vtkMath.radiansFromDegrees(model.startAngle);
if (startAngleRad < 0) {
startAngleRad += 2.0 * Math.PI;
}
const segmentAngleRad = vtkMath.radiansFromDegrees(model.segmentAngle);
const angleIncRad = segmentAngleRad / model.resolution;
let pointType = VtkDataTypes.FLOAT;
if (model.outputPointsPrecision === DesiredOutputPrecision.SINGLE) {
pointType = VtkDataTypes.FLOAT;
} else if (model.outputPointsPrecision === DesiredOutputPrecision.DOUBLE) {
pointType = VtkDataTypes.DOUBLE;
}
const points = vtkPoints.newInstance({
dataType: pointType
});
points.setNumberOfPoints(numPts);
const tcoords = vtkDataArray.newInstance({
numberOfComponents: 2,
size: numPts * 2,
dataType: VtkDataTypes.FLOAT,
name: 'TextureCoordinates'
});
const lines = vtkCellArray.newInstance();
lines.allocate(numLines);
const skipLastPoint = model.close && isClosedShape;
let theta = startAngleRad;
let pointIndex = 0;
for (let i = 0; i <= resolution; ++i, theta += angleIncRad) {
const quotient = Math.floor(theta / (2.0 * Math.PI));
const normalizedTheta = theta - quotient * 2.0 * Math.PI;
let thetaEllipse = Math.atan(Math.tan(normalizedTheta) * model.ratio);
if (normalizedTheta > Math.PI / 2 && normalizedTheta <= Math.PI) {
thetaEllipse += Math.PI;
} else if (normalizedTheta > Math.PI && normalizedTheta <= 1.5 * Math.PI) {
thetaEllipse -= Math.PI;
}
const cosTheta = Math.cos(thetaEllipse);
const sinTheta = Math.sin(thetaEllipse);
const p = [model.center[0] + a * cosTheta * majorRadiusVect[0] + b * sinTheta * orthogonalVect[0], model.center[1] + a * cosTheta * majorRadiusVect[1] + b * sinTheta * orthogonalVect[1], model.center[2] + a * cosTheta * majorRadiusVect[2] + b * sinTheta * orthogonalVect[2]];
tc[0] = i / resolution;
tc[1] = 0.0;
if (i !== resolution || !skipLastPoint) {
points.setPoint(pointIndex, ...p);
tcoords.setTuple(pointIndex, tc);
pointIndex++;
}
}
const actualNumPts = pointIndex;
const pointIds = [];
for (let k = 0; k < actualNumPts - 1; ++k) {
pointIds.push(k);
}
if (model.close) {
pointIds.push(0);
} else {
pointIds.push(actualNumPts - 1);
}
lines.insertNextCell(pointIds);
output.setPoints(points);
output.getPointData().setTCoords(tcoords);
output.setLines(lines);
outData[0] = output;
};
}
// ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------
const DEFAULT_VALUES = {
center: [0.0, 0.0, 0.0],
normal: [0.0, 0.0, 1.0],
majorRadiusVector: [1.0, 0.0, 0.0],
startAngle: 0.0,
segmentAngle: 90.0,
resolution: 100,
close: false,
outputPointsPrecision: DesiredOutputPrecision.SINGLE,
ratio: 1.0
};
// ----------------------------------------------------------------------------
function extend(publicAPI, model, initialValues = {}) {
Object.assign(model, DEFAULT_VALUES, initialValues);
// Ensure resolution is at least 1
if (model.resolution < 1) {
model.resolution = 1;
}
// Build VTK API
macro.obj(publicAPI, model);
macro.algo(publicAPI, model, 0, 1);
macro.setGet(publicAPI, model, ['resolution', 'startAngle', 'segmentAngle', 'close', 'outputPointsPrecision', 'ratio']);
macro.setGetArray(publicAPI, model, ['center', 'normal', 'majorRadiusVector'], 3);
vtkEllipseArcSource(publicAPI, model);
}
// ----------------------------------------------------------------------------
const newInstance = macro.newInstance(extend, 'vtkEllipseArcSource');
// ----------------------------------------------------------------------------
var vtkEllipseArcSource$1 = {
newInstance,
extend
};
export { vtkEllipseArcSource$1 as default, extend, newInstance };