@kitware/vtk.js
Version:
Visualization Toolkit for the Web
201 lines (154 loc) • 8.44 kB
JavaScript
import _defineProperty from '@babel/runtime/helpers/defineProperty';
import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
import macro from '../../macros.js';
import vtkCellArray from '../../Common/Core/CellArray.js';
import vtkPolygon from '../../Common/DataModel/Polygon.js';
import vtkPolyData from '../../Common/DataModel/PolyData.js';
import { VtkDataTypes } from '../../Common/Core/DataArray/Constants.js';
import { vtkCCSMakePolysFromLines, vtkCCSJoinLooseEnds, vtkCCSFindTrueEdges, vtkCCSMakeHoleyPolys, vtkCCSCutHoleyPolys, vtkCCSSplitAtPinchPoints, vtkCCSTriangulate } from './ContourTriangulator/helper.js';
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); 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 = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
var vtkErrorMacro = macro.vtkErrorMacro;
var TRIANGULATION_ERROR_DISPLAY = false;
function triangulateContours(polyData, firstLine, numLines, polys, normal) {
var triangulatePolys = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true;
var triangulationFailure = false; // If no cut lines were generated, there's nothing to do
if (numLines <= 0) {
return false;
}
var points = polyData.getPoints(); // Join all the new lines into connected groups, i.e. polygons.
// If we are lucky these will be simple, convex polygons. But
// we can't count on that.
var newPolys = [];
var incompletePolys = [];
var oriented = normal != null;
vtkCCSMakePolysFromLines(polyData, firstLine, firstLine + numLines, oriented, newPolys, incompletePolys); // if no normal specified, then compute one from largest contour
var computedNormal = normal;
if (normal == null) {
var maxnorm = 0;
var n = [];
for (var i = 0; i < newPolys.length; i++) {
var norm = vtkPolygon.getNormal(newPolys[i], points, n);
if (norm > maxnorm) {
maxnorm = norm;
computedNormal[0] = n[0];
computedNormal[1] = n[1];
computedNormal[2] = n[2];
}
}
} // Join any loose ends. If the input was a closed surface then there
// will not be any loose ends, so this is provided as a service to users
// who want to clip a non-closed surface.
vtkCCSJoinLooseEnds(newPolys, incompletePolys, points, computedNormal); // Some points might be in the middle of straight line segments.
// These points can be removed without changing the shape of the
// polys, and removing them makes triangulation more stable.
// Unfortunately removing these points also means that the polys
// will no longer form a watertight cap over the cut.
var polyEdges = [];
var originalEdges = [];
vtkCCSFindTrueEdges(newPolys, points, polyEdges, originalEdges); // Next we have to check for polygons with holes, i.e. polygons that
// have other polygons inside. Each polygon is "grouped" with the
// polygons that make up its holes.
// Initialize each group to hold just one polygon.
var numNewPolys = newPolys.length;
var polyGroups = [];
for (var _i = 0; _i < numNewPolys; _i++) {
polyGroups[_i] = [_i];
} // Find out which polys are holes in larger polys. Create a group
// for each poly where the first member of the group is the larger
// poly, and all other members are the holes. The number of polyGroups
// will be the same as the number of polys, and any polys that are
// holes will have a matching empty group.
vtkCCSMakeHoleyPolys(newPolys, points, polyGroups, polyEdges, originalEdges, computedNormal, oriented); // Make cuts to create simple polygons out of the holey polys.
// After this is done, each polyGroup will have exactly 1 polygon,
// and no polys will be holes. This is currently the most computationally
// expensive part of the process.
if (!vtkCCSCutHoleyPolys(newPolys, points, polyGroups, polyEdges, computedNormal)) {
triangulationFailure = true;
} // Some polys might be self-intersecting. Split the polys at each intersection point.
vtkCCSSplitAtPinchPoints(newPolys, points, polyGroups, polyEdges, computedNormal, oriented); // ------ Triangulation code ------
// Go through all polys and triangulate them
for (var polyId = 0; polyId < polyGroups.length; polyId++) {
// If group is empty, then poly was a hole without a containing poly
if (polyGroups[polyId].length === 0) {
// eslint-disable-next-line no-continue
continue;
}
if (!triangulatePolys) {
polys.insertNextCell(originalEdges.slice(1, originalEdges.length));
} else if (!vtkCCSTriangulate(newPolys[polyId], points, polyEdges[polyId], originalEdges, polys, computedNormal)) {
triangulationFailure = false; // Diagnostic code: show the polys as outlines
}
}
return !triangulationFailure;
} // ---------------------------------------------------
function triangulatePolygon(polygon, points, triangles) {
var poly = _toConsumableArray(polygon);
var polys = [poly];
var originalEdges = [];
var polyEdges = [];
vtkCCSFindTrueEdges(polys, points, polyEdges, originalEdges);
var edges = polyEdges[0];
var success = true;
var normal = [];
var norm = vtkPolygon.getNormal(poly, points, normal);
if (norm !== 0) {
success = vtkCCSTriangulate(poly, points, edges, originalEdges, triangles, normal);
}
return success;
}
var STATIC = {
triangulateContours: triangulateContours,
triangulatePolygon: triangulatePolygon
};
function vtkContourTriangulator(publicAPI, model) {
// Set our className
model.classHierarchy.push('vtkContourTriangulator');
publicAPI.requestData = function (inData, outData) {
// implement requestData
var input = inData[0];
var output = vtkPolyData.newInstance();
outData[0] = output;
if (!input) {
vtkErrorMacro('Invalid or missing input');
return false;
}
var triangulationError = false;
var lines = input.getLines();
if (lines == null || lines.getNumberOfCells() === 0) {
return true;
}
input.buildCells();
var polysArray = vtkCellArray.newInstance({
dataType: VtkDataTypes.DOUBLE,
empty: true
});
output.setPolys(polysArray);
output.setPoints(input.getPoints());
output.getPointData().passData(input.getPointData());
triangulationError = !triangulateContours(input, input.getNumberOfVerts(), lines.getNumberOfCells(), polysArray, [], model.triangulatePolys);
if (triangulationError && TRIANGULATION_ERROR_DISPLAY) {
vtkErrorMacro('Triangulation failed, output might have holes.');
}
return true;
};
} // ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------
var DEFAULT_VALUES = {
triangulatePolys: true
}; // ----------------------------------------------------------------------------
function extend(publicAPI, model) {
var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
Object.assign(model, DEFAULT_VALUES, initialValues); // Make this a VTK object
macro.obj(publicAPI, model); // Also make it an algorithm with one input and one output
macro.algo(publicAPI, model, 1, 1);
macro.setGet(publicAPI, model, ['triangulate']); // Object specific methods
vtkContourTriangulator(publicAPI, model);
} // ----------------------------------------------------------------------------
var newInstance = macro.newInstance(extend, 'vtkContourTriangulator'); // ----------------------------------------------------------------------------
var vtkContourTriangulator$1 = _objectSpread({
newInstance: newInstance,
extend: extend
}, STATIC);
export { STATIC, vtkContourTriangulator$1 as default, extend, newInstance };