@kitware/vtk.js 25.4.0 → 25.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/Common/Core/CellArray.d.ts +20 -8
  2. package/Common/Core/CellArray.js +25 -6
  3. package/Common/Core/DataArray.d.ts +159 -15
  4. package/Common/Core/DataArray.js +181 -26
  5. package/Common/Core/Math/index.js +1 -1
  6. package/Common/Core/Math.js +1 -1
  7. package/Common/Core/Points.d.ts +6 -5
  8. package/Common/Core/Points.js +8 -4
  9. package/Common/DataModel/AbstractPointLocator.d.ts +54 -0
  10. package/Common/DataModel/AbstractPointLocator.js +40 -0
  11. package/Common/DataModel/DataSetAttributes/FieldData.d.ts +33 -22
  12. package/Common/DataModel/DataSetAttributes/FieldData.js +91 -9
  13. package/Common/DataModel/DataSetAttributes.d.ts +44 -0
  14. package/Common/DataModel/DataSetAttributes.js +11 -0
  15. package/Common/DataModel/IncrementalOctreeNode.d.ts +282 -0
  16. package/Common/DataModel/IncrementalOctreeNode.js +621 -0
  17. package/Common/DataModel/IncrementalOctreePointLocator.d.ts +61 -0
  18. package/Common/DataModel/IncrementalOctreePointLocator.js +342 -0
  19. package/Common/DataModel/Line.js +1 -1
  20. package/Common/DataModel/Locator.d.ts +43 -0
  21. package/Common/DataModel/Locator.js +37 -0
  22. package/Common/DataModel/Plane.js +1 -1
  23. package/Common/DataModel/Polygon/Constants.js +12 -0
  24. package/Common/DataModel/Polygon.d.ts +38 -4
  25. package/Common/DataModel/Polygon.js +210 -6
  26. package/Common/DataModel/Quad/Constants.js +9 -0
  27. package/Common/DataModel/Quad.d.ts +91 -0
  28. package/Common/DataModel/Quad.js +235 -0
  29. package/Common/DataModel/Triangle.d.ts +106 -81
  30. package/Common/DataModel/Triangle.js +1 -1
  31. package/Common/Transform/LandmarkTransform.js +1 -1
  32. package/Filters/Core/PolyDataNormals.js +1 -1
  33. package/Filters/General/ClipClosedSurface/Constants.js +10 -0
  34. package/Filters/General/ClipClosedSurface/ccsEdgeLocator.js +40 -0
  35. package/Filters/General/ClipClosedSurface.d.ts +95 -0
  36. package/Filters/General/ClipClosedSurface.js +970 -0
  37. package/Filters/General/ContourTriangulator/Constants.js +6 -0
  38. package/Filters/General/ContourTriangulator/helper.js +1951 -0
  39. package/Filters/General/ContourTriangulator.d.ts +122 -0
  40. package/Filters/General/ContourTriangulator.js +200 -0
  41. package/Filters/General/ImageMarchingCubes.js +1 -1
  42. package/Filters/General/MoleculeToRepresentation.js +1 -1
  43. package/Filters/General/OBBTree.js +1 -1
  44. package/Filters/General/TubeFilter.js +1 -1
  45. package/Filters/General/WindowedSincPolyDataFilter.js +1 -1
  46. package/Filters/Sources/PlaneSource.js +1 -1
  47. package/Filters/Texture/TextureMapToPlane.js +1 -1
  48. package/IO/Core/DataAccessHelper/HtmlDataAccessHelper.js +4 -8
  49. package/IO/Core/DataAccessHelper/HttpDataAccessHelper.js +6 -14
  50. package/IO/Core/DataAccessHelper/JSZipDataAccessHelper.js +60 -57
  51. package/IO/Core/ZipMultiDataSetReader.js +19 -29
  52. package/IO/Core/ZipMultiDataSetWriter.js +7 -23
  53. package/IO/Misc/SkyboxReader.js +67 -75
  54. package/IO/XML/XMLReader.js +2 -2
  55. package/IO/XML/XMLWriter.js +2 -2
  56. package/Interaction/Manipulators/KeyboardCameraManipulator.js +1 -1
  57. package/Interaction/Manipulators/MouseCameraAxisRotateManipulator.js +1 -1
  58. package/Interaction/Manipulators/MouseCameraTrackballPanManipulator.js +1 -1
  59. package/Interaction/Manipulators/MouseCameraTrackballRotateManipulator.js +1 -1
  60. package/Interaction/Manipulators/MouseCameraUnicamManipulator.js +1 -1
  61. package/Interaction/Manipulators/MouseCameraUnicamRotateManipulator.js +1 -1
  62. package/Interaction/Style/InteractorStyleMPRSlice.js +1 -1
  63. package/Interaction/Style/InteractorStyleTrackballCamera.js +16 -0
  64. package/Proxy/Core/View2DProxy.js +1 -1
  65. package/Rendering/Core/Actor2D.d.ts +12 -6
  66. package/Rendering/Core/Camera.js +1 -1
  67. package/Rendering/Core/CellPicker.js +3 -2
  68. package/Rendering/Core/ColorTransferFunction/ColorMaps.d.ts +24 -0
  69. package/Rendering/Core/Light.js +1 -1
  70. package/Rendering/Core/Picker.js +1 -1
  71. package/Rendering/Core/Property2D.d.ts +1 -1
  72. package/Rendering/Core/VolumeProperty.d.ts +4 -4
  73. package/Rendering/Core/VolumeProperty.js +1 -1
  74. package/Rendering/OpenGL/PolyDataMapper.js +1 -1
  75. package/Rendering/OpenGL/RenderWindow/ContextProxy.js +65 -0
  76. package/Rendering/OpenGL/RenderWindow.js +3 -1
  77. package/Rendering/WebGPU/BufferManager.js +1 -1
  78. package/Rendering/WebGPU/ForwardPass.js +93 -15
  79. package/Rendering/WebGPU/OpaquePass.js +1 -1
  80. package/Rendering/WebGPU/OrderIndependentTranslucentPass.js +1 -1
  81. package/Rendering/WebGPU/RenderEncoder.js +9 -5
  82. package/Rendering/WebGPU/RenderWindow.js +15 -13
  83. package/Rendering/WebGPU/TextureView.js +15 -2
  84. package/Rendering/WebGPU/VolumePass.js +1 -1
  85. package/Widgets/Core/StateBuilder/orientationMixin.js +1 -1
  86. package/Widgets/Manipulators/LineManipulator.js +1 -1
  87. package/Widgets/Manipulators/TrackballManipulator.js +1 -1
  88. package/Widgets/Representations/ResliceCursorContextRepresentation.js +1 -1
  89. package/Widgets/Widgets3D/LineWidget/behavior.js +1 -1
  90. package/Widgets/Widgets3D/LineWidget/helpers.js +1 -1
  91. package/Widgets/Widgets3D/ResliceCursorWidget/behavior.js +1 -1
  92. package/Widgets/Widgets3D/ResliceCursorWidget/helpers.js +1 -1
  93. package/Widgets/Widgets3D/ResliceCursorWidget.js +1 -1
  94. package/Widgets/Widgets3D/ShapeWidget/behavior.js +1 -1
  95. package/index.d.ts +8 -0
  96. package/index.js +0 -2
  97. package/package.json +3 -4
  98. package/ThirdParty/index.js +0 -9
@@ -0,0 +1,1951 @@
1
+ import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
2
+ import macro from '../../../macros.js';
3
+ import vtkPoints from '../../../Common/Core/Points.js';
4
+ import { s as subtract, k as cross, d as dot, n as norm, f as distance2BetweenPoints, l as add, m as normalize } from '../../../Common/Core/Math/index.js';
5
+ import vtkLine from '../../../Common/DataModel/Line.js';
6
+ import vtkPolygon from '../../../Common/DataModel/Polygon.js';
7
+ import vtkIncrementalOctreePointLocator from '../../../Common/DataModel/IncrementalOctreePointLocator.js';
8
+ import { VtkDataTypes } from '../../../Common/Core/DataArray/Constants.js';
9
+ import { CCS_POLYGON_TOLERANCE } from './Constants.js';
10
+ import { PolygonWithPointIntersectionState } from '../../../Common/DataModel/Polygon/Constants.js';
11
+
12
+ var vtkErrorMacro = macro.vtkErrorMacro;
13
+ /**
14
+ * Reverse the elements between the indices firstIdx and lastIdx of the given array arr.
15
+ *
16
+ * @param {Array|TypedArray} arr
17
+ * @param {Number} firstIdx
18
+ * @param {Number} lastIdx
19
+ */
20
+
21
+ function reverseElements(arr) {
22
+ var firstIdx = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
23
+ var lastIdx = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined;
24
+ var first = firstIdx !== null && firstIdx !== void 0 ? firstIdx : 0;
25
+ var last = lastIdx !== null && lastIdx !== void 0 ? lastIdx : arr.length - 1;
26
+ var mid = first + Math.floor((last - first) / 2);
27
+
28
+ for (var i = first; i <= mid; ++i) {
29
+ var _ref = [arr[last - (i - first)], arr[i]];
30
+ arr[i] = _ref[0];
31
+ arr[last - (i - first)] = _ref[1];
32
+ }
33
+ } // ---------------------------------------------------
34
+
35
+ /**
36
+ * Compute the quality of a triangle.
37
+ *
38
+ * @param {Vector3} p0
39
+ * @param {Vector3} p1
40
+ * @param {Vector3} p2
41
+ * @param {Vector3} normal
42
+ * @returns {Number}
43
+ */
44
+
45
+ function vtkCCSTriangleQuality(p0, p1, p2, normal) {
46
+ var u = [];
47
+ var v = [];
48
+ var w = [];
49
+ subtract(p1, p0, u);
50
+ subtract(p2, p1, v);
51
+ subtract(p0, p2, w);
52
+ var area2 = (u[1] * v[2] - u[2] * v[1]) * normal[0] + (u[2] * v[0] - u[0] * v[2]) * normal[1] + (u[0] * v[1] - u[1] * v[0]) * normal[2];
53
+ var perim = Math.sqrt(u[0] * u[0] + u[1] * u[1] + u[2] * u[2]) + Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]) + Math.sqrt(w[0] * w[0] + w[1] * w[1] + w[2] * w[2]);
54
+ perim *= perim; // square the perimeter
55
+
56
+ perim = perim !== 0 ? perim : 1.0; // use a normalization factor so equilateral quality is 1.0
57
+
58
+ return area2 / perim * 10.392304845413264;
59
+ } // ---------------------------------------------------
60
+
61
+ /**
62
+ * Insert a triangle, and subdivide that triangle if one of
63
+ * its edges originally had more than two points before
64
+ * vtkCCSFindTrueEdges was called. Is called by vtkCCSTriangulate.
65
+ *
66
+ * @param {vtkCellArray} polys
67
+ * @param {Array|TypedArray} poly
68
+ * @param {Vector3} trids
69
+ * @param {Array|TypedArray} polyEdges
70
+ * @param {Array|TypedArray} originalEdges
71
+ */
72
+
73
+ function vtkCCSInsertTriangle(polys, poly, trids, polyEdges, originalEdges) {
74
+ var nextVert = [1, 2, 0]; // To store how many of originalEdges match
75
+
76
+ var edgeCount = 0;
77
+ var edgeLocs = [-1, -1, -1]; // Check for original edge matches
78
+
79
+ for (var vert = 0; vert < 3; vert++) {
80
+ var currId = trids[vert];
81
+ var edgeLoc = polyEdges[currId];
82
+
83
+ if (edgeLoc >= 0) {
84
+ var nextId = currId + 1;
85
+
86
+ if (nextId === poly.length) {
87
+ nextId = 0;
88
+ } // Is the triangle edge a polygon edge?
89
+
90
+
91
+ if (nextId === trids[nextVert[vert]]) {
92
+ edgeLocs[vert] = edgeLoc;
93
+ edgeCount++;
94
+ }
95
+ }
96
+ }
97
+
98
+ if (edgeCount === 0) {
99
+ // No special edge handling, so just do one triangle
100
+ polys.insertNextCell([poly[trids[0]], poly[trids[1]], poly[trids[2]]]);
101
+ } else {
102
+ // Make triangle fans for edges with extra points
103
+ var edgePts = [[poly[trids[0]], poly[trids[1]]], [poly[trids[1]], poly[trids[2]]], [poly[trids[2]], poly[trids[0]]]]; // Find out which edge has the most extra points
104
+
105
+ var maxPoints = 0;
106
+ var currSide = 0;
107
+
108
+ for (var i = 0; i < 3; i++) {
109
+ if (edgeLocs[i] >= 0) {
110
+ var _edgeLoc = edgeLocs[i];
111
+ var npts = originalEdges[_edgeLoc];
112
+ var pts = originalEdges.slice(_edgeLoc + 1, _edgeLoc + 1 + npts);
113
+
114
+ if (!(edgePts[i][0] === pts[0] || edgePts[i][1] === pts[npts - 1])) {
115
+ vtkErrorMacro('assertion error in vtkCCSInsertTriangle');
116
+ }
117
+
118
+ if (npts > maxPoints) {
119
+ maxPoints = npts;
120
+ currSide = i;
121
+ }
122
+
123
+ edgePts[i] = pts;
124
+ }
125
+ } // Find the edges before/after the edge with most points
126
+
127
+
128
+ var prevSide = (currSide + 2) % 3;
129
+ var nextSide = (currSide + 1) % 3; // If other edges have only 2 points, nothing to do with them
130
+
131
+ var prevNeeded = edgePts[prevSide].length > 2;
132
+ var nextNeeded = edgePts[nextSide].length > 2; // The tail is the common point in the triangle fan
133
+
134
+ var tailPtIds = [];
135
+ tailPtIds[prevSide] = edgePts[currSide][1];
136
+ tailPtIds[currSide] = edgePts[prevSide][0];
137
+ tailPtIds[nextSide] = edgePts[currSide][edgePts[currSide].length - 2]; // Go through the sides and make the fans
138
+
139
+ for (var side = 0; side < 3; side++) {
140
+ if ((side !== prevSide || prevNeeded) && (side !== nextSide || nextNeeded)) {
141
+ var m = 0;
142
+ var n = edgePts[side].length - 1;
143
+
144
+ if (side === currSide) {
145
+ m += prevNeeded;
146
+ n -= nextNeeded;
147
+ }
148
+
149
+ for (var k = m; k < n; k++) {
150
+ polys.insertNextCell([edgePts[side][k], edgePts[side][k + 1], tailPtIds[side]]);
151
+ }
152
+ }
153
+ }
154
+ }
155
+ } // ---------------------------------------------------
156
+
157
+ /**
158
+ * Triangulate a polygon that has been simplified by FindTrueEdges.
159
+ * This will re-insert the original edges. The output triangles are
160
+ * appended to "polys" and, for each stored triangle, "color" will
161
+ * be added to "scalars". The final two arguments (polygon and
162
+ * triangles) are only for temporary storage.
163
+ * The return value is true if triangulation was successful.
164
+ *
165
+ * @param {Array} poly
166
+ * @param {vtkPoints} points
167
+ * @param {Array} polyEdges
168
+ * @param {Array} originalEdges
169
+ * @param {vtkCellArray} polys
170
+ * @param {Vector3} normal
171
+ * @returns {boolean}
172
+ */
173
+
174
+ function vtkCCSTriangulate(poly, points, polyEdges, originalEdges, polys, normal) {
175
+ var n = poly.length; // If the poly is a line, then skip it
176
+
177
+ if (n < 3) {
178
+ return true;
179
+ } // If the poly is a triangle, then pass it
180
+
181
+
182
+ if (n === 3) {
183
+ var trids = [0, 1, 2];
184
+ vtkCCSInsertTriangle(polys, poly, trids, polyEdges, originalEdges);
185
+ return true;
186
+ } // If the poly has 4 or more points, triangulate it
187
+
188
+
189
+ var triangulationFailure = false;
190
+ var ppoint = [];
191
+ var point = [];
192
+ var npoint = [];
193
+ var i = 0;
194
+ var j = 0;
195
+ var k = 0;
196
+ var verts = [];
197
+ verts.length = n;
198
+
199
+ for (i = 0; i < n; i++) {
200
+ verts[i] = [i, 0];
201
+ } // compute the triangle quality for each vert
202
+
203
+
204
+ k = n - 2;
205
+ points.getPoint(poly[verts[k][0]], point);
206
+ i = n - 1;
207
+ points.getPoint(poly[verts[i][0]], npoint);
208
+ var concave = 0;
209
+ var maxq = 0;
210
+ var maxi = 0;
211
+
212
+ for (j = 0; j < n; j++) {
213
+ var _ref2 = [point, npoint, ppoint];
214
+ ppoint = _ref2[0];
215
+ point = _ref2[1];
216
+ npoint = _ref2[2];
217
+ points.getPoint(poly[verts[j][0]], npoint);
218
+ var q = vtkCCSTriangleQuality(ppoint, point, npoint, normal);
219
+
220
+ if (q > maxq) {
221
+ maxi = i;
222
+ maxq = q;
223
+ }
224
+
225
+ concave += q < 0;
226
+ verts[i][1] = q;
227
+ i = j;
228
+ }
229
+
230
+ var foundEar; // perform the ear-cut triangulation
231
+
232
+ for (;;) {
233
+ // if no potential ears were found, then fail
234
+ if (maxq <= Number.MIN_VALUE) {
235
+ triangulationFailure = true;
236
+ break;
237
+ }
238
+
239
+ i = maxi;
240
+ j = i + 1 !== n ? i + 1 : 0;
241
+ k = i !== 0 ? i - 1 : n - 1;
242
+
243
+ if (verts[i][1] > 0) {
244
+ foundEar = true;
245
+ points.getPoint(poly[verts[j][0]], npoint);
246
+ points.getPoint(poly[verts[k][0]], ppoint); // only do ear check if there are concave vertices
247
+
248
+ if (concave) {
249
+ // get the normal of the split plane
250
+ var v = [];
251
+ var u = [];
252
+ subtract(npoint, ppoint, v);
253
+ cross(v, normal, u);
254
+ var d = dot(ppoint, u);
255
+ var jj = j + 1 !== n ? j + 1 : 0;
256
+ var x = [];
257
+ points.getPoint(poly[verts[jj][0]], x);
258
+ var side = dot(x, u) < d;
259
+ var foundNegative = side; // check for crossings of the split plane
260
+
261
+ jj = jj + 1 !== n ? jj + 1 : 0;
262
+ var y = [];
263
+ var s = [];
264
+ var t = [];
265
+
266
+ for (; foundEar && jj !== k; jj = jj + 1 !== n ? jj + 1 : 0) {
267
+ var _ref3 = [y, x];
268
+ x = _ref3[0];
269
+ y = _ref3[1];
270
+ points.getPoint(poly[verts[jj][0]], x);
271
+ var sside = dot(x, u) < d; // XOR
272
+
273
+ if (side ? !sside : sside) {
274
+ side = !side;
275
+ foundNegative = true;
276
+ foundEar = vtkLine.intersection(ppoint, npoint, x, y, s, t) === vtkLine.IntersectionState.NO_INTERSECTION;
277
+ }
278
+ }
279
+
280
+ foundEar && (foundEar = foundNegative);
281
+ }
282
+
283
+ if (!foundEar) {
284
+ // don't try again until it is split
285
+ verts[i][1] = Number.MIN_VALUE;
286
+ } else {
287
+ // create a triangle from vertex and neighbors
288
+ var _trids = [verts[i][0], verts[j][0], verts[k][0]];
289
+ vtkCCSInsertTriangle(polys, poly, _trids, polyEdges, originalEdges); // remove the vertex i
290
+
291
+ verts.splice(i, 1);
292
+ k -= i === 0;
293
+ j -= j !== 0; // break if this was final triangle
294
+
295
+ if (--n < 3) {
296
+ break;
297
+ } // re-compute quality of previous point
298
+
299
+
300
+ var kk = k !== 0 ? k - 1 : n - 1;
301
+ points.getPoint(poly[verts[kk][0]], point);
302
+ var kq = vtkCCSTriangleQuality(point, ppoint, npoint, normal);
303
+ concave -= verts[k][1] < 0 && kq >= 0;
304
+ verts[k][1] = kq; // re-compute quality of next point
305
+
306
+ var _jj = j + 1 !== n ? j + 1 : 0;
307
+
308
+ points.getPoint(poly[verts[_jj][0]], point);
309
+ var jq = vtkCCSTriangleQuality(ppoint, npoint, point, normal);
310
+ concave -= verts[j][1] < 0 && jq >= 0;
311
+ verts[j][1] = jq;
312
+ }
313
+ } // find the highest-quality ear candidate
314
+
315
+
316
+ maxi = 0;
317
+ maxq = verts[0][1];
318
+
319
+ for (i = 1; i < n; i++) {
320
+ var _q = verts[i][1];
321
+
322
+ if (_q > maxq) {
323
+ maxi = i;
324
+ maxq = _q;
325
+ }
326
+ }
327
+ }
328
+
329
+ return !triangulationFailure;
330
+ } // ---------------------------------------------------
331
+
332
+ /**
333
+ * Create polygons from line segments.
334
+ *
335
+ * @param {vtkPolyData} polyData
336
+ * @param {Number} firstLine
337
+ * @param {Number} endLine
338
+ * @param {Boolean} oriented
339
+ * @param {Array} newPolys
340
+ * @param {Array} incompletePolys
341
+ */
342
+
343
+ function vtkCCSMakePolysFromLines(polyData, firstLine, endLine, oriented, newPolys, incompletePolys) {
344
+ var npts = 0;
345
+ var pts = []; // Bitfield for marking lines as used
346
+
347
+ var usedLines = new Uint8Array(endLine - firstLine); // defaults to 0
348
+ // Require cell links to get lines from pointIds
349
+
350
+ polyData.buildLinks(polyData.getPoints().getNumberOfPoints());
351
+ var numNewPolys = 0;
352
+ var remainingLines = endLine - firstLine;
353
+
354
+ while (remainingLines > 0) {
355
+ // Create a new poly
356
+ var polyId = numNewPolys++;
357
+ var poly = [];
358
+ newPolys.push(poly);
359
+ var lineId = 0;
360
+ var completePoly = false; // start the poly
361
+
362
+ for (lineId = firstLine; lineId < endLine; lineId++) {
363
+ if (!usedLines[lineId - firstLine]) {
364
+ pts = polyData.getCellPoints(lineId).cellPointIds;
365
+ npts = pts.length;
366
+ var n = npts;
367
+
368
+ if (npts > 2 && pts[0] === pts[npts - 1]) {
369
+ n = npts - 1;
370
+ completePoly = true;
371
+ }
372
+
373
+ poly.length = n;
374
+
375
+ for (var i = 0; i < n; i++) {
376
+ poly[i] = pts[i];
377
+ }
378
+
379
+ break;
380
+ }
381
+ }
382
+
383
+ usedLines[lineId - firstLine] = 1;
384
+ remainingLines--;
385
+ var noLinesMatch = remainingLines === 0 && !completePoly;
386
+
387
+ while (!completePoly && !noLinesMatch && remainingLines > 0) {
388
+ // This is cleared if a match is found
389
+ noLinesMatch = true; // Number of points in the poly
390
+
391
+ var npoly = poly.length;
392
+ var lineEndPts = [];
393
+ var endPts = [poly[npoly - 1], poly[0]]; // For both open ends of the polygon
394
+
395
+ for (var endIdx = 0; endIdx < 2; endIdx++) {
396
+ var matches = [];
397
+ var cells = polyData.getPointCells(endPts[endIdx]); // Go through all lines that contain this endpoint
398
+
399
+ for (var icell = 0; icell < cells.length; icell++) {
400
+ lineId = cells[icell];
401
+
402
+ if (lineId >= firstLine && lineId < endLine && !usedLines[lineId - firstLine]) {
403
+ pts = polyData.getCellPoints(lineId).cellPointIds;
404
+ npts = pts.length;
405
+ lineEndPts[0] = pts[0];
406
+ lineEndPts[1] = pts[npts - 1]; // Check that poly end matches line end
407
+
408
+ if (endPts[endIdx] === lineEndPts[endIdx] || !oriented && endPts[endIdx] === lineEndPts[1 - endIdx]) {
409
+ matches.push(lineId);
410
+ }
411
+ }
412
+ }
413
+
414
+ if (!matches.length === 0) {
415
+ // Multiple matches mean we need to decide which path to take
416
+ if (matches.length > 1) {
417
+ // Remove double-backs
418
+ var k = matches.length;
419
+
420
+ do {
421
+ lineId = matches[--k];
422
+ pts = polyData.getCellPoints(lineId).cellPointIds;
423
+ npts = pts.length;
424
+ lineEndPts[0] = pts[0];
425
+ lineEndPts[1] = pts[npts - 1]; // check if line is reversed
426
+
427
+ var r = endPts[endIdx] !== lineEndPts[endIdx];
428
+
429
+ if (!r && (endIdx === 0 && poly[npoly - 2] === pts[1] || endIdx === 1 && poly[1] === pts[npts - 2]) || r && (endIdx === 0 && poly[npoly - 2] === pts[npts - 2] || endIdx === 1 && poly[1] === pts[1])) {
430
+ matches.splice(k, 1);
431
+ }
432
+ } while (k > 0 && matches.length > 1); // If there are multiple matches due to intersections,
433
+ // they should be dealt with here.
434
+
435
+ }
436
+
437
+ lineId = matches[0];
438
+ pts = polyData.getCellPoints(lineId).cellPointIds;
439
+ npts = pts.length;
440
+ lineEndPts[0] = pts[0];
441
+ lineEndPts[1] = pts[npts - 1]; // Do both ends match?
442
+
443
+ if (endPts[endIdx] === lineEndPts[endIdx]) {
444
+ completePoly = endPts[1 - endIdx] === lineEndPts[1 - endIdx];
445
+ } else {
446
+ completePoly = endPts[1 - endIdx] === lineEndPts[endIdx];
447
+ }
448
+
449
+ if (endIdx === 0) {
450
+ for (var _i = 1; _i < npts - (completePoly ? 1 : 0); _i++) {
451
+ poly.push(pts[_i]);
452
+ }
453
+ } else {
454
+ for (var _i2 = completePoly ? 1 : 0; _i2 < npts - 1; _i2++) {
455
+ poly.unshift(pts[_i2]);
456
+ }
457
+ }
458
+
459
+ if (endPts[endIdx] !== lineEndPts[endIdx]) {
460
+ // reverse the ids in the added line
461
+ var pit = poly.length;
462
+ var ptsIt = completePoly ? 1 : 0;
463
+ var ptsEnd = npts - 1;
464
+
465
+ if (endIdx === 1) {
466
+ pit = npts - 1 - (completePoly ? 1 : 0);
467
+ ptsIt = pts + 1;
468
+ ptsEnd = pts + npts - (completePoly ? 1 : 0);
469
+ }
470
+
471
+ while (ptsIt !== ptsEnd) {
472
+ poly[--pit] = poly[ptsIt++];
473
+ }
474
+ }
475
+
476
+ usedLines[lineId - firstLine] = 1;
477
+ remainingLines--;
478
+ noLinesMatch = false;
479
+ }
480
+ }
481
+ } // Check for incomplete polygons
482
+
483
+
484
+ if (noLinesMatch) {
485
+ incompletePolys.push(polyId);
486
+ }
487
+ }
488
+ } // ---------------------------------------------------
489
+
490
+ /**
491
+ * Join polys that have loose ends, as indicated by incompletePolys.
492
+ * Any polys created will have a normal opposite to the supplied normal,
493
+ * and any new edges that are created will be on the hull of the point set.
494
+ * Shorter edges will be preferred over long edges.
495
+ *
496
+ * @param {Array[]} polys
497
+ * @param {Array} incompletePolys
498
+ * @param {vtkPoints} points
499
+ * @param {Vector3} normal
500
+ */
501
+
502
+ function vtkCCSJoinLooseEnds(polys, incompletePolys, points, normal) {
503
+ // Relative tolerance for checking whether an edge is on the hull
504
+ var tol = CCS_POLYGON_TOLERANCE; // A list of polys to remove when everything is done
505
+
506
+ var removePolys = [];
507
+ var p1 = [];
508
+ var p2 = [];
509
+ var poly1;
510
+ var poly2;
511
+ var pt1;
512
+ var pt2;
513
+ var dMin;
514
+ var iMin;
515
+ var v;
516
+ var d;
517
+ var n = incompletePolys.length;
518
+
519
+ while (n !== 0) {
520
+ poly1 = polys[incompletePolys[n - 1]];
521
+ pt1 = poly1[poly1.length - 1];
522
+ points.getPoint(pt1, p1);
523
+ dMin = Number.MAX_VALUE;
524
+ iMin = 0;
525
+
526
+ for (var _i3 = 0; _i3 < n; _i3++) {
527
+ poly2 = polys[incompletePolys[_i3]];
528
+ pt2 = poly2[0];
529
+ points.getPoint(pt2, p2); // The next few steps verify that edge [p1, p2] is on the hull
530
+
531
+ v = [p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]];
532
+ d = norm(v);
533
+
534
+ if (d !== 0) {
535
+ v[0] /= d;
536
+ v[1] /= d;
537
+ v[2] /= d;
538
+ } // Compute the midpoint of the edge
539
+
540
+
541
+ var pm = [0.5 * (p1[0] + p2[0]), 0.5 * (p1[1] + p2[1]), 0.5 * (p1[2] + p2[2])]; // Create a plane equation
542
+
543
+ var pc = [];
544
+ cross(normal, v, pc);
545
+ pc[3] = -dot(pc, pm); // Check that all points are inside the plane. If they aren't, then
546
+ // the edge is not on the hull of the pointset.
547
+
548
+ var badPoint = false;
549
+ var m = polys.length;
550
+ var p = [];
551
+
552
+ for (var j = 0; j < m && !badPoint; j++) {
553
+ var poly = polys[j];
554
+ var npts = poly.length;
555
+
556
+ for (var k = 0; k < npts; k++) {
557
+ var ptId = poly[k];
558
+
559
+ if (ptId !== pt1 && ptId !== pt2) {
560
+ points.getPoint(ptId, p);
561
+ var val = p[0] * pc[0] + p[1] * pc[1] + p[2] * pc[2] + pc[3];
562
+ var r2 = distance2BetweenPoints(p, pm); // Check distance from plane against the tolerance
563
+
564
+ if (val < 0 && val * val > tol * tol * r2) {
565
+ badPoint = true;
566
+ break;
567
+ }
568
+ }
569
+ } // If no bad points, then this edge is a candidate
570
+
571
+
572
+ if (!badPoint && d < dMin) {
573
+ dMin = d;
574
+ iMin = _i3;
575
+ }
576
+ }
577
+ } // If a match was found, append the polys
578
+
579
+
580
+ if (dMin < Number.MAX_VALUE) {
581
+ // Did the poly match with itself?
582
+ if (iMin === n - 1) {
583
+ // Mark the poly as closed
584
+ incompletePolys.pop();
585
+ } else {
586
+ var _poly;
587
+
588
+ var id2 = incompletePolys[iMin]; // Combine the polys
589
+ // for (let i = 1; i < polys[id2].length; i++) {
590
+ // poly1.push(polys[id2][i]);
591
+ // }
592
+
593
+ (_poly = poly1).push.apply(_poly, _toConsumableArray(polys[id2])); // Erase the second poly
594
+
595
+
596
+ removePolys.push(id2);
597
+ incompletePolys.splice(iMin, 1);
598
+ }
599
+ } else {
600
+ // If no match, erase this poly from consideration
601
+ removePolys.push(incompletePolys[n - 1]);
602
+ incompletePolys.pop();
603
+ }
604
+
605
+ n = incompletePolys.length;
606
+ } // Remove polys that couldn't be completed
607
+
608
+
609
+ removePolys.sort(function (a, b) {
610
+ return a - b;
611
+ });
612
+ var i = removePolys.length;
613
+
614
+ while (i > 0) {
615
+ // Remove items in reverse order
616
+ polys.splice(removePolys[--i], 1);
617
+ } // Clear the incompletePolys vector, it's indices are no longer valid
618
+
619
+
620
+ incompletePolys.length = 0;
621
+ } // ---------------------------------------------------
622
+
623
+ /**
624
+ * Given three vectors p.p1, p.p2, and p.p3, this routine
625
+ * checks to see if progressing from p1 to p2 to p3 is a clockwise
626
+ * or counterclockwise progression with respect to the normal.
627
+ * The return value is -1 for clockwise, +1 for counterclockwise,
628
+ * and 0 if any two of the vectors are coincident.
629
+ *
630
+ * @param {Vector3} p
631
+ * @param {Vector3} p1
632
+ * @param {Vector3} p2
633
+ * @param {Vector3} p3
634
+ * @param {Vector3} normal
635
+ * @returns {Number}
636
+ */
637
+
638
+ function vtkCCSVectorProgression(p, p1, p2, p3, normal) {
639
+ var v1 = [p1[0] - p[0], p1[1] - p[1], p1[2] - p[2]];
640
+ var v2 = [p2[0] - p[0], p2[1] - p[1], p2[2] - p[2]];
641
+ var v3 = [p3[0] - p[0], p3[1] - p[1], p3[2] - p[2]];
642
+ var w1 = [];
643
+ var w2 = [];
644
+ cross(v2, v1, w1);
645
+ cross(v2, v3, w2);
646
+ var s1 = dot(w1, normal);
647
+ var s2 = dot(w2, normal);
648
+
649
+ if (s1 !== 0 && s2 !== 0) {
650
+ var sb1 = s1 < 0;
651
+ var sb2 = s2 < 0; // if sines have different signs
652
+ // XOR
653
+
654
+ if (sb1 ? !sb2 : sb2) {
655
+ // return -1 if s2 is -ve
656
+ return 1 - 2 * sb2;
657
+ }
658
+
659
+ var c1 = dot(v2, v1);
660
+ var l1 = norm(v1);
661
+ var c2 = dot(v2, v3);
662
+ var l2 = norm(v3); // ck is the difference of the cosines, flipped in sign if sines are +ve
663
+
664
+ var ck = (c2 * l2 - c1 * l1) * (1 - sb1 * 2);
665
+
666
+ if (ck !== 0) {
667
+ // return the sign of ck
668
+ return 1 - 2 * (ck < 0);
669
+ }
670
+ }
671
+
672
+ return 0;
673
+ } // ---------------------------------------------------
674
+
675
+ /**
676
+ * Check for self-intersection. Split the figure-eights.
677
+ * This assumes that all intersections occur at existing
678
+ * vertices, i.e. no new vertices will be created. Returns
679
+ * the number of splits made.
680
+ *
681
+ * @param {Array[]} polys
682
+ * @param {vtkPoints} points
683
+ * @param {Array} polyGroups
684
+ * @param {Array} polyEdges
685
+ * @param {Vector3} normal
686
+ * @param {Boolean} oriented
687
+ */
688
+
689
+ function vtkCCSSplitAtPinchPoints(polys, points, polyGroups, polyEdges, normal, oriented) {
690
+ var tryPoints = vtkPoints.newInstance({
691
+ dataType: VtkDataTypes.DOUBLE,
692
+ empty: true
693
+ });
694
+ var locator = vtkIncrementalOctreePointLocator.newInstance();
695
+ var splitCount = 0;
696
+ var poly;
697
+ var n;
698
+ var bounds;
699
+ var tol;
700
+
701
+ for (var i = 0; i < polys.length; i++) {
702
+ poly = polys[i];
703
+ n = poly.length;
704
+ bounds = [];
705
+ tol = CCS_POLYGON_TOLERANCE * Math.sqrt(vtkPolygon.getBounds(poly, points, bounds));
706
+
707
+ if (tol === 0) {
708
+ // eslint-disable-next-line no-continue
709
+ continue;
710
+ }
711
+
712
+ tryPoints.initialize();
713
+ locator.setTolerance(tol);
714
+ locator.initPointInsertion(tryPoints, bounds);
715
+ var foundMatch = false;
716
+ var idx1 = 0;
717
+ var idx2 = 0;
718
+ var unique = 0;
719
+ var point = [];
720
+ var p1 = [];
721
+ var p2 = [];
722
+ var p3 = [];
723
+
724
+ for (idx2 = 0; idx2 < n; idx2++) {
725
+ points.getPoint(poly[idx2], point);
726
+
727
+ var _locator$insertUnique = locator.insertUniquePoint(point, 0),
728
+ success = _locator$insertUnique.success,
729
+ pointIdx = _locator$insertUnique.pointIdx;
730
+
731
+ if (!success) {
732
+ // Need vertIdx to match poly indices, so force point insertion
733
+ locator.insertNextPoint(point); // Do the points have different pointIds?
734
+
735
+ idx1 = pointIdx;
736
+ unique = poly[idx2] !== poly[idx1];
737
+
738
+ if (idx2 > idx1 + 2 - unique && n + idx1 > idx2 + 2 - unique) {
739
+ if (oriented) {
740
+ // Make sure that splitting this poly won't create a hole poly
741
+ var prevIdx = n + idx1 - 1;
742
+ var midIdx = idx1 + 1;
743
+ var nextIdx = idx2 + 1;
744
+
745
+ if (prevIdx >= n) {
746
+ prevIdx -= n;
747
+ }
748
+
749
+ if (midIdx >= n) {
750
+ midIdx -= n;
751
+ }
752
+
753
+ if (nextIdx >= n) {
754
+ nextIdx -= n;
755
+ }
756
+
757
+ points.getPoint(poly[prevIdx], p1);
758
+ points.getPoint(poly[midIdx], p2);
759
+ points.getPoint(poly[nextIdx], p3);
760
+
761
+ if (vtkCCSVectorProgression(point, p1, p2, p3, normal) > 0) {
762
+ foundMatch = true;
763
+ break;
764
+ }
765
+ } else {
766
+ foundMatch = true;
767
+ break;
768
+ }
769
+ }
770
+ }
771
+ }
772
+
773
+ if (foundMatch) {
774
+ splitCount++; // Split off a new poly
775
+
776
+ var m = idx2 - idx1;
777
+ var oldPoly = polys[i];
778
+ var oldEdges = polyEdges[i];
779
+ var newPoly1 = oldPoly.slice(idx1, idx1 + m + unique);
780
+ var newEdges1 = oldEdges.slice(idx1, idx1 + m + unique);
781
+ var newPoly2 = new Array(n - m + unique);
782
+ var newEdges2 = new Array(n - m + unique);
783
+
784
+ if (unique) {
785
+ newEdges1[m] = -1;
786
+ } // The poly that is split off, which might have more intersections
787
+
788
+
789
+ for (var j = 0; j < idx1 + unique; j++) {
790
+ newPoly2[j] = oldPoly[j];
791
+ newEdges2[j] = oldEdges[j];
792
+ }
793
+
794
+ if (unique) {
795
+ newEdges2[idx1] = -1;
796
+ }
797
+
798
+ for (var k = idx2; k < n; k++) {
799
+ newPoly2[k - m + unique] = oldPoly[k];
800
+ newEdges2[k - m + unique] = oldEdges[k];
801
+ }
802
+
803
+ polys[i] = newPoly1;
804
+ polyEdges[i] = newEdges1;
805
+ polys.push(newPoly2);
806
+ polyEdges.push(newEdges2); // Unless polygroup was clear (because poly was reversed),
807
+ // make a group with one entry for the new poly
808
+
809
+ polyGroups.length = polys.length;
810
+
811
+ if (polyGroups[i].length > 0) {
812
+ polyGroups[polys.length - 1].push(polys.length - 1);
813
+ }
814
+ }
815
+ }
816
+
817
+ return splitCount;
818
+ } // ---------------------------------------------------
819
+
820
+ /**
821
+ * The polygons might have a lot of extra points, i.e. points
822
+ * in the middle of the edges. Remove those points, but keep
823
+ * the original edges as polylines in the originalEdges array.
824
+ * Only original edges with more than two points will be kept.
825
+ *
826
+ * @param {Array[]} polys
827
+ * @param {vtkPoints} points
828
+ * @param {Array} polyEdges
829
+ * @param {Array} originalEdges
830
+ */
831
+
832
+ function vtkCCSFindTrueEdges(polys, points, polyEdges, originalEdges) {
833
+ // Tolerance^2 for angle to see if line segments are parallel
834
+ var atol2 = CCS_POLYGON_TOLERANCE * CCS_POLYGON_TOLERANCE;
835
+ var p0 = [];
836
+ var p1 = [];
837
+ var p2 = [];
838
+ var v1 = [];
839
+ var v2 = [];
840
+ var l1;
841
+ var l2;
842
+
843
+ for (var polyId = 0; polyId < polys.length; polyId++) {
844
+ var oldPoly = polys[polyId];
845
+ var n = oldPoly.length;
846
+ var newEdges = [];
847
+ polyEdges.push(newEdges); // Only useful if poly has more than three sides
848
+
849
+ if (n < 4) {
850
+ newEdges[0] = -1;
851
+ newEdges[1] = -1;
852
+ newEdges[2] = -1; // eslint-disable-next-line no-continue
853
+
854
+ continue;
855
+ } // While we remove points, m keeps track of how many points are left
856
+
857
+
858
+ var m = n; // Compute bounds for tolerance
859
+
860
+ var bounds = [];
861
+ var tol2 = vtkPolygon.getBounds(oldPoly, points, bounds) * atol2; // The new poly
862
+
863
+ var newPoly = [];
864
+ var cornerPointId = 0;
865
+ var oldOriginalId = -1; // Keep the partial edge from before the first corner is found
866
+
867
+ var partialEdge = [];
868
+ var cellCount = 0;
869
+ points.getPoint(oldPoly[n - 1], p0);
870
+ points.getPoint(oldPoly[0], p1);
871
+ subtract(p1, p0, v1);
872
+ l1 = dot(v1, v1);
873
+
874
+ for (var j = 0; j < n; j++) {
875
+ var k = j + 1;
876
+
877
+ if (k >= n) {
878
+ k -= n;
879
+ }
880
+
881
+ points.getPoint(oldPoly[k], p2);
882
+ subtract(p2, p1, v2);
883
+ l2 = dot(v2, v2); // Dot product is |v1||v2|cos(theta)
884
+
885
+ var c = dot(v1, v2); // sin^2(theta) = (1 - cos^2(theta))
886
+ // and c*c = l1*l2*cos^2(theta)
887
+
888
+ var s2 = l1 * l2 - c * c; // In the small angle approximation, sin(theta) == theta, so
889
+ // s2/(l1*l2) is the angle that we want to check, but it's not
890
+ // a valid check if l1 or l2 is very close to zero.
891
+
892
+ var pointId = oldPoly[j]; // Keep the point if:
893
+ // 1) removing it would create a 2-point poly OR
894
+ // 2) it's more than "tol" distance from the prev point AND
895
+ // 3) the angle is greater than atol:
896
+
897
+ if (m <= 3 || l1 > tol2 && (c < 0 || l1 < tol2 || l2 < tol2 || s2 > l1 * l2 * atol2)) {
898
+ // Complete the previous edge only if the final point count
899
+ // will be greater than two
900
+ if (cellCount > 1) {
901
+ if (pointId !== oldOriginalId) {
902
+ originalEdges.push(pointId);
903
+ cellCount++;
904
+ } // Update the number of segments in the edge
905
+
906
+
907
+ var countLocation = originalEdges.length - cellCount - 1;
908
+ originalEdges[countLocation] = cellCount;
909
+ newEdges.push(countLocation);
910
+ } else if (cellCount === 0) {
911
+ partialEdge.push(pointId);
912
+ } else {
913
+ newEdges.push(-1);
914
+ }
915
+
916
+ newPoly.push(pointId); // Start a new edge with cornerPointId as a "virtual" point
917
+
918
+ cornerPointId = pointId;
919
+ oldOriginalId = pointId;
920
+ cellCount = 1; // Rotate to the next point
921
+
922
+ p0[0] = p2[0];
923
+ p0[1] = p2[1];
924
+ p0[2] = p2[2];
925
+ p1[0] = p2[0];
926
+ p1[1] = p2[1];
927
+ p1[2] = p2[2];
928
+ v1[0] = v2[0];
929
+ v1[1] = v2[1];
930
+ v1[2] = v2[2];
931
+ l1 = l2;
932
+ } else {
933
+ if (cellCount > 0 && pointId !== oldOriginalId) {
934
+ // First check to see if we have to add cornerPointId
935
+ if (cellCount === 1) {
936
+ originalEdges.push(1); // new edge
937
+
938
+ originalEdges.push(cornerPointId);
939
+ } // Then add the new point
940
+
941
+
942
+ originalEdges.push(pointId);
943
+ oldOriginalId = pointId;
944
+ cellCount++;
945
+ } else {
946
+ // No corner yet, so save the point
947
+ partialEdge.push(pointId);
948
+ } // Reduce the count
949
+
950
+
951
+ m--; // Join the previous two segments, since the point was removed
952
+
953
+ p1[0] = p2[0];
954
+ p1[1] = p2[1];
955
+ p1[2] = p2[2];
956
+ subtract(p2, p0, v1);
957
+ l1 = dot(v1, v1);
958
+ }
959
+ } // Add the partial edge to the end
960
+
961
+
962
+ for (var ii = 0; ii < partialEdge.length; ii++) {
963
+ var _pointId = partialEdge[ii];
964
+
965
+ if (_pointId !== oldOriginalId) {
966
+ if (cellCount === 1) {
967
+ originalEdges.push(1); // new edge
968
+
969
+ originalEdges.push(cornerPointId);
970
+ }
971
+
972
+ originalEdges.push(_pointId);
973
+ oldOriginalId = _pointId;
974
+ cellCount++;
975
+ }
976
+ } // Finalize
977
+
978
+
979
+ if (cellCount > 1) {
980
+ // Update the number of segments in the edge
981
+ var _countLocation = originalEdges.length - cellCount - 1;
982
+
983
+ originalEdges[_countLocation] = cellCount;
984
+ newEdges.push(_countLocation);
985
+ }
986
+
987
+ polys[polyId] = newPoly;
988
+ }
989
+ } // ---------------------------------------------------
990
+
991
+ /**
992
+ * Reverse a cleaned-up polygon along with the info about
993
+ * all of its original vertices.
994
+ *
995
+ * @param {Array} poly
996
+ * @param {Array} edges
997
+ * @param {Array} originalEdges
998
+ */
999
+
1000
+ function vtkCCSReversePoly(poly, edges, originalEdges) {
1001
+ reverseElements(poly, 1, poly.length - 1);
1002
+ edges.reverse();
1003
+
1004
+ for (var i = 0; i < edges.length; i++) {
1005
+ if (edges[i] >= 0) {
1006
+ var firstPtsIdx = edges[i] + 1;
1007
+ var npts = originalEdges[edges[i]];
1008
+ reverseElements(originalEdges, firstPtsIdx, firstPtsIdx + npts - 1);
1009
+ }
1010
+ }
1011
+ } // ---------------------------------------------------
1012
+
1013
+ /**
1014
+ * Check the sense of the polygon against the given normal. Returns
1015
+ * zero if the normal is zero.
1016
+ *
1017
+ * @param {Array} poly
1018
+ * @param {vtkPoints} points
1019
+ * @param {Vector3} normal
1020
+ */
1021
+
1022
+ function vtkCCSCheckPolygonSense(poly, points, normal) {
1023
+ // Compute the normal
1024
+ var pnormal = [0.0, 0.0, 0.0];
1025
+ var p0 = [];
1026
+ var p1 = [];
1027
+ var p2 = [];
1028
+ var v1 = [];
1029
+ var v2 = [];
1030
+ var v = [];
1031
+ points.getPoint(poly[0], p0);
1032
+ points.getPoint(poly[1], p1);
1033
+ subtract(p1, p0, v1);
1034
+
1035
+ for (var jj = 2; jj < poly.length; jj++) {
1036
+ points.getPoint(poly[jj], p2);
1037
+ subtract(p2, p0, v2);
1038
+ cross(v1, v2, v);
1039
+ add(pnormal, v, pnormal);
1040
+ p1[0] = p2[0];
1041
+ p1[1] = p2[1];
1042
+ p1[2] = p2[2];
1043
+ v1[0] = v2[0];
1044
+ v1[1] = v2[1];
1045
+ v1[2] = v2[2];
1046
+ } // Check the normal
1047
+
1048
+
1049
+ var d = dot(pnormal, normal);
1050
+ return {
1051
+ isNormalNotZero: d !== 0,
1052
+ sense: d > 0
1053
+ };
1054
+ } // ---------------------------------------------------
1055
+
1056
+ /**
1057
+ * Check whether innerPoly is inside outerPoly.
1058
+ * The normal is needed to verify the polygon orientation.
1059
+ * The values of pp, bounds, and tol2 must be precomputed
1060
+ * by calling vtkCCSPrepareForPolyInPoly() on outerPoly.
1061
+ *
1062
+ * @param {Array} outerPoly
1063
+ * @param {Array} innerPoly
1064
+ * @param {vtkPoints} points
1065
+ * @param {Vector3} normal
1066
+ * @param {Float64Array} pp
1067
+ * @param {Bounds} bounds
1068
+ * @param {Number} tol2
1069
+ */
1070
+
1071
+ function vtkCCSPolyInPoly(outerPoly, innerPoly, points, normal, pp, bounds, tol2) {
1072
+ // Find a vertex of poly "j" that isn't on the edge of poly "i".
1073
+ // This is necessary or the PointInPolygon might return "true"
1074
+ // based only on roundoff error.
1075
+ var n = outerPoly.length;
1076
+ var m = innerPoly.length;
1077
+ var p = [];
1078
+ var q1 = [];
1079
+ var q2 = [];
1080
+
1081
+ for (var jj = 0; jj < m; jj++) {
1082
+ // Semi-randomize the point order
1083
+ // eslint-disable-next-line no-bitwise
1084
+ var kk = (jj >> 1) + (jj & 1) * (m + 1 >> 1);
1085
+ points.getPoint(innerPoly[kk], p);
1086
+ var intersectionState = vtkPolygon.pointInPolygon(p, pp, bounds, normal);
1087
+
1088
+ if (intersectionState === PolygonWithPointIntersectionState.FAILURE) {
1089
+ vtkErrorMacro('Error finding point in polygon in vtkCCSPolyInPoly');
1090
+ }
1091
+
1092
+ if (intersectionState !== PolygonWithPointIntersectionState.OUTSIDE) {
1093
+ var pointOnEdge = 0;
1094
+ points.getPoint(outerPoly[n - 1], q1);
1095
+
1096
+ for (var ii = 0; ii < n; ii++) {
1097
+ points.getPoint(outerPoly[ii], q2); // This method returns distance squared
1098
+
1099
+ var _vtkLine$distanceToLi = vtkLine.distanceToLine(p, q1, q2),
1100
+ distance = _vtkLine$distanceToLi.distance;
1101
+
1102
+ if (distance < tol2) {
1103
+ pointOnEdge = 1;
1104
+ break;
1105
+ }
1106
+
1107
+ q1[0] = q2[0];
1108
+ q1[1] = q2[1];
1109
+ q1[2] = q2[2];
1110
+ }
1111
+
1112
+ if (!pointOnEdge) {
1113
+ // Good result, point is in polygon
1114
+ return true;
1115
+ }
1116
+ }
1117
+ } // No matches found
1118
+
1119
+
1120
+ return false;
1121
+ } // ---------------------------------------------------
1122
+
1123
+ /**
1124
+ * Precompute values needed for the PolyInPoly check.
1125
+ * The values that are returned are as follows:
1126
+ * pp: an array of the polygon vertices
1127
+ * bounds: the polygon bounds
1128
+ * tol2: a tolerance value based on the size of the polygon
1129
+ * (note: pp must be pre-allocated to the 3*outerPoly.length)
1130
+ *
1131
+ * @param {Array} outerPoly
1132
+ * @param {vtkPoints} points
1133
+ * @param {Float64Array} pp
1134
+ * @param {Bounds} bounds
1135
+ */
1136
+
1137
+ function vtkCCSPrepareForPolyInPoly(outerPoly, points, pp, bounds) {
1138
+ var n = outerPoly.length;
1139
+
1140
+ if (n === 0) {
1141
+ return 0.0; // to avoid false positive warning about uninitialized value
1142
+ } // Pull out the points
1143
+
1144
+
1145
+ var point = [];
1146
+ var j = 0;
1147
+
1148
+ for (var i = 0; i < n; i++) {
1149
+ points.getPoint(outerPoly[i], point);
1150
+ pp[j++] = point[0];
1151
+ pp[j++] = point[1];
1152
+ pp[j++] = point[2];
1153
+ } // Find the bounding box and tolerance for the polygon
1154
+
1155
+
1156
+ return vtkPolygon.getBounds(outerPoly, points, bounds) * (CCS_POLYGON_TOLERANCE * CCS_POLYGON_TOLERANCE);
1157
+ } // ---------------------------------------------------
1158
+
1159
+ /**
1160
+ * Check for polygons within polygons. Group the polygons
1161
+ * if they are within each other. Reverse the sense of
1162
+ * the interior "hole" polygons. A hole within a hole
1163
+ * will be reversed twice and will become its own group.
1164
+ *
1165
+ * @param {Array} newPolys
1166
+ * @param {vtkPoints} points
1167
+ * @param {Array} polyGroups
1168
+ * @param {Array} polyEdges
1169
+ * @param {Array} originalEdges
1170
+ * @param {Vector3} normal
1171
+ * @param {Boolean} oriented
1172
+ */
1173
+
1174
+ function vtkCCSMakeHoleyPolys(newPolys, points, polyGroups, polyEdges, originalEdges, normal, oriented) {
1175
+ var numNewPolys = newPolys.length;
1176
+
1177
+ if (numNewPolys <= 1) {
1178
+ return;
1179
+ } // Use bit arrays to keep track of inner polys
1180
+
1181
+
1182
+ var polyReversed = [];
1183
+ var innerPolys = []; // GroupCount is an array only needed for unoriented polys
1184
+
1185
+ var groupCount;
1186
+
1187
+ if (!oriented) {
1188
+ groupCount = new Int32Array(numNewPolys);
1189
+ } // Find the maximum poly size
1190
+
1191
+
1192
+ var nmax = 1;
1193
+
1194
+ for (var kk = 0; kk < numNewPolys; kk++) {
1195
+ nmax = Math.max(nmax, newPolys[kk].length);
1196
+ } // These are some values needed for poly-in-poly checks
1197
+
1198
+
1199
+ var pp = new Float64Array(3 * nmax);
1200
+ var bounds = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0];
1201
+ var tol2; // Go through all polys
1202
+
1203
+ for (var i = 0; i < numNewPolys; i++) {
1204
+ var n = newPolys[i].length;
1205
+
1206
+ if (n < 3) {
1207
+ // eslint-disable-next-line no-continue
1208
+ continue;
1209
+ } // Check if poly is reversed
1210
+
1211
+
1212
+ var _vtkCCSCheckPolygonSe = vtkCCSCheckPolygonSense(newPolys[i], points, normal),
1213
+ isNormalNotZero = _vtkCCSCheckPolygonSe.isNormalNotZero,
1214
+ sense = _vtkCCSCheckPolygonSe.sense;
1215
+
1216
+ if (isNormalNotZero) {
1217
+ polyReversed[i] = !sense;
1218
+ } // Precompute some values needed for poly-in-poly checks
1219
+
1220
+
1221
+ tol2 = vtkCCSPrepareForPolyInPoly(newPolys[i], points, pp, bounds); // Look for polygons inside of this one
1222
+
1223
+ for (var j = 0; j < numNewPolys; j++) {
1224
+ if (j !== i && newPolys[j].length >= 3) {
1225
+ // Make sure polygon i is not in polygon j
1226
+ var pg = polyGroups[j];
1227
+
1228
+ if (!pg.includes(i)) {
1229
+ if (vtkCCSPolyInPoly(newPolys[i], newPolys[j], points, normal, pp.subarray(3 * n), bounds, tol2)) {
1230
+ // Add to group
1231
+ polyGroups[i].push(j);
1232
+
1233
+ if (groupCount) {
1234
+ groupCount[j] += 1;
1235
+ }
1236
+ }
1237
+ }
1238
+ }
1239
+ }
1240
+ }
1241
+
1242
+ if (!oriented) {
1243
+ // build a stack of polys that aren't inside other polys=
1244
+ var outerPolyStack = [];
1245
+
1246
+ for (var ll = 0; ll < numNewPolys; ll++) {
1247
+ if (groupCount[ll] === 0) {
1248
+ outerPolyStack.push(ll);
1249
+ }
1250
+ }
1251
+
1252
+ var _j;
1253
+
1254
+ while (outerPolyStack.length > 0) {
1255
+ _j = outerPolyStack.length - 1;
1256
+ outerPolyStack.pop();
1257
+
1258
+ if (polyReversed[_j]) {
1259
+ vtkCCSReversePoly(newPolys[_j], polyEdges[_j], originalEdges);
1260
+ polyReversed[_j] = false;
1261
+ }
1262
+
1263
+ if (polyGroups[_j].length > 1) {
1264
+ // Convert the group into a bit array, to make manipulation easier
1265
+ innerPolys.length = 0;
1266
+
1267
+ for (var k = 1; k < polyGroups[_j].length; k++) {
1268
+ var jj = polyGroups[_j][k];
1269
+
1270
+ if (groupCount[jj] > 1) {
1271
+ groupCount[jj] -= 2;
1272
+
1273
+ if (groupCount[jj] === 0) {
1274
+ outerPolyStack.push(jj);
1275
+ }
1276
+ } else {
1277
+ innerPolys[jj] = 1;
1278
+ polyGroups[jj].length = 0;
1279
+
1280
+ if (!polyReversed[jj]) {
1281
+ vtkCCSReversePoly(newPolys[jj], polyEdges[jj], originalEdges);
1282
+ polyReversed[jj] = false;
1283
+ }
1284
+ }
1285
+ } // Use the bit array to recreate the polyGroup
1286
+
1287
+
1288
+ polyGroups[_j].length = 0;
1289
+
1290
+ polyGroups[_j].push(_j);
1291
+
1292
+ for (var _jj2 = 0; _jj2 < numNewPolys; _jj2++) {
1293
+ if (innerPolys[_jj2]) {
1294
+ polyGroups[_j].push(_jj2);
1295
+ }
1296
+ }
1297
+ }
1298
+ }
1299
+ } else {
1300
+ // oriented
1301
+ for (var _j2 = 0; _j2 < numNewPolys; _j2++) {
1302
+ // Remove the groups for reversed polys
1303
+ if (polyReversed[_j2]) {
1304
+ polyGroups[_j2].length = 0;
1305
+ } // Polys inside the interior polys have their own groups, so remove
1306
+ // them from this group
1307
+ else if (polyGroups[_j2].length > 1) {
1308
+ // Convert the group into a bit array, to make manipulation easier
1309
+ innerPolys.length = 0;
1310
+
1311
+ for (var _k = 1; _k < polyGroups[_j2].length; _k++) {
1312
+ innerPolys[polyGroups[_j2][_k]] = true;
1313
+ } // Look for non-reversed polys inside this one
1314
+
1315
+
1316
+ for (var _kk = 1; _kk < polyGroups[_j2].length; _kk++) {
1317
+ // jj is the index of the inner poly
1318
+ var _jj3 = polyGroups[_j2][_kk]; // If inner poly is not reversed then
1319
+
1320
+ if (!polyReversed[_jj3]) {
1321
+ // Remove that poly and all polys inside of it from the group
1322
+ for (var ii = 0; ii < polyGroups[_jj3].length; ii++) {
1323
+ innerPolys[polyGroups[_jj3][ii]] = false;
1324
+ }
1325
+ }
1326
+ } // Use the bit array to recreate the polyGroup
1327
+
1328
+
1329
+ polyGroups[_j2].length = 0;
1330
+
1331
+ polyGroups[_j2].push(_j2);
1332
+
1333
+ for (var _jj4 = 0; _jj4 < numNewPolys; _jj4++) {
1334
+ if (innerPolys[_jj4]) {
1335
+ polyGroups[_j2].push(_jj4);
1336
+ }
1337
+ }
1338
+ }
1339
+ }
1340
+ } // delete[] groupCount;
1341
+
1342
+ } // ---------------------------------------------------
1343
+
1344
+ /**
1345
+ * Check line segment with point Ids (i, j) to make sure that it
1346
+ * doesn't cut through the edges of any polys in the group.
1347
+ * Return value of zero means check failed and the cut is not
1348
+ * usable.
1349
+ *
1350
+ * @param {Array[]} polys
1351
+ * @param {vtkPoints} points
1352
+ * @param {Vector3} normal
1353
+ * @param {Array} polyGroup
1354
+ * @param {Number} outerPolyId
1355
+ * @param {Number} innerPolyId
1356
+ * @param {Number} outerIdx
1357
+ * @param {Number} innerIdx
1358
+ */
1359
+
1360
+ function vtkCCSCheckCut(polys, points, normal, polyGroup, outerPolyId, innerPolyId, outerIdx, innerIdx) {
1361
+ var ptId1 = polys[outerPolyId][outerIdx];
1362
+ var ptId2 = polys[innerPolyId][innerIdx];
1363
+ var tol = CCS_POLYGON_TOLERANCE;
1364
+ var p1 = [];
1365
+ var p2 = [];
1366
+ points.getPoint(ptId1, p1);
1367
+ points.getPoint(ptId2, p2);
1368
+ var w = [];
1369
+ subtract(p2, p1, w);
1370
+ var l = normalize(w); // Cuts between coincident points are good
1371
+
1372
+ if (l === 0) {
1373
+ return true;
1374
+ } // Define a tolerance with units of distance squared
1375
+
1376
+
1377
+ var tol2 = l * l * tol * tol; // Check the sense of the cut: it must be pointing "in" for both polys.
1378
+
1379
+ var polyId = outerPolyId;
1380
+ var polyIdx = outerIdx;
1381
+ var r = p1;
1382
+ var r1 = [];
1383
+ var r2 = p2;
1384
+ var r3 = [];
1385
+
1386
+ for (var ii = 0; ii < 2; ii++) {
1387
+ var poly = polys[polyId];
1388
+ var n = poly.length;
1389
+ var prevIdx = n - polyIdx - 1;
1390
+ var nextIdx = polyIdx + 1;
1391
+
1392
+ if (prevIdx >= n) {
1393
+ prevIdx -= n;
1394
+ }
1395
+
1396
+ if (nextIdx >= n) {
1397
+ nextIdx -= n;
1398
+ }
1399
+
1400
+ points.getPoint(poly[prevIdx], r1);
1401
+ points.getPoint(poly[nextIdx], r3);
1402
+
1403
+ if (vtkCCSVectorProgression(r, r1, r2, r3, normal) > 0) {
1404
+ return false;
1405
+ }
1406
+
1407
+ polyId = innerPolyId;
1408
+ polyIdx = innerIdx;
1409
+ r = p2;
1410
+ r2 = p1;
1411
+ } // Check for intersections of the cut with polygon edges.
1412
+ // First, create a cut plane that divides space at the cut line.
1413
+
1414
+
1415
+ var pc = [];
1416
+ cross(normal, w, pc);
1417
+ pc[3] = -dot(pc, p1);
1418
+
1419
+ for (var i = 0; i < polyGroup.length; i++) {
1420
+ var _poly2 = polys[polyGroup[i]];
1421
+ var _n = _poly2.length;
1422
+ var q1 = [];
1423
+ var q2 = [];
1424
+ var qtId1 = _poly2[_n - 1];
1425
+ points.getPoint(qtId1, q1);
1426
+ var v1 = pc[0] * q1[0] + pc[1] * q1[1] + pc[2] * q1[2] + pc[3];
1427
+ var c1 = v1 > 0;
1428
+
1429
+ for (var j = 0; j < _n; j++) {
1430
+ var qtId2 = _poly2[j];
1431
+ points.getPoint(qtId2, q2);
1432
+ var v2 = pc[0] * q2[0] + pc[1] * q2[1] + pc[2] * q2[2] + pc[3];
1433
+ var c2 = v2 > 0; // If lines share an endpoint, they can't intersect,
1434
+ // so don't bother with the check.
1435
+
1436
+ if (ptId1 !== qtId1 && ptId1 !== qtId2 && ptId2 !== qtId1 && ptId2 !== qtId2) {
1437
+ // Check for intersection
1438
+ if ((c1 ? !c2 : c2) || v1 * v1 < tol2 || v2 * v2 < tol2) {
1439
+ subtract(q2, q1, w);
1440
+
1441
+ if (dot(w, w) > 0) {
1442
+ var qc = [];
1443
+ cross(w, normal, qc);
1444
+ qc[3] = -dot(qc, q1);
1445
+ var u1 = qc[0] * p1[0] + qc[1] * p1[1] + qc[2] * p1[2] + qc[3];
1446
+ var u2 = qc[0] * p2[0] + qc[1] * p2[1] + qc[2] * p2[2] + qc[3];
1447
+ var d1 = u1 > 0;
1448
+ var d2 = u2 > 0;
1449
+
1450
+ if (d1 ? !d2 : d2) {
1451
+ // One final check to make sure endpoints aren't coincident
1452
+ var p = p1;
1453
+ var q = q1;
1454
+
1455
+ if (v2 * v2 < v1 * v1) {
1456
+ p = p2;
1457
+ }
1458
+
1459
+ if (u2 * u2 < u1 * u1) {
1460
+ q = q2;
1461
+ }
1462
+
1463
+ if (distance2BetweenPoints(p, q) > tol2) {
1464
+ return false;
1465
+ }
1466
+ }
1467
+ }
1468
+ }
1469
+ }
1470
+
1471
+ qtId1 = qtId2;
1472
+ q1[0] = q2[0];
1473
+ q1[1] = q2[1];
1474
+ q1[2] = q2[2];
1475
+ v1 = v2;
1476
+ c1 = c2;
1477
+ }
1478
+ }
1479
+
1480
+ return true;
1481
+ } // ---------------------------------------------------
1482
+
1483
+ /**
1484
+ * Check the quality of a cut between an outer and inner polygon.
1485
+ * An ideal cut is one that forms a 90 degree angle with each
1486
+ * line segment that it joins to. Smaller values indicate a
1487
+ * higher quality cut.
1488
+ *
1489
+ * @param {Array} outerPoly
1490
+ * @param {Array} innerPoly
1491
+ * @param {Number} i
1492
+ * @param {Number} j
1493
+ * @param {vtkPoints} points
1494
+ */
1495
+
1496
+ function vtkCCSCutQuality(outerPoly, innerPoly, i, j, points) {
1497
+ var n = outerPoly.length;
1498
+ var m = innerPoly.length;
1499
+ var a = i > 0 ? i - 1 : n - 1;
1500
+ var b = i < n - 1 ? i + 1 : 0;
1501
+ var c = j > 0 ? j - 1 : m - 1;
1502
+ var d = j < m - 1 ? j + 1 : 0;
1503
+ var p0 = [];
1504
+ var p1 = [];
1505
+ var p2 = [];
1506
+ points.getPoint(outerPoly[i], p1);
1507
+ points.getPoint(innerPoly[j], p2);
1508
+ var v1 = [];
1509
+ var v2 = [];
1510
+ subtract(p2, p1, v1);
1511
+ var l1 = dot(v1, v1);
1512
+ var l2;
1513
+ var qmax = 0;
1514
+ var q;
1515
+ points.getPoint(outerPoly[a], p0);
1516
+ subtract(p0, p1, v2);
1517
+ l2 = dot(v2, v2);
1518
+
1519
+ if (l2 > 0) {
1520
+ q = dot(v1, v2);
1521
+ q *= q / l2;
1522
+
1523
+ if (q > qmax) {
1524
+ qmax = q;
1525
+ }
1526
+ }
1527
+
1528
+ points.getPoint(outerPoly[b], p0);
1529
+ subtract(p0, p1, v2);
1530
+ l2 = dot(v2, v2);
1531
+
1532
+ if (l2 > 0) {
1533
+ q = dot(v1, v2);
1534
+ q *= q / l2;
1535
+
1536
+ if (q > qmax) {
1537
+ qmax = q;
1538
+ }
1539
+ }
1540
+
1541
+ points.getPoint(innerPoly[c], p0);
1542
+ subtract(p2, p0, v2);
1543
+ l2 = dot(v2, v2);
1544
+
1545
+ if (l2 > 0) {
1546
+ q = dot(v1, v2);
1547
+ q *= q / l2;
1548
+
1549
+ if (q > qmax) {
1550
+ qmax = q;
1551
+ }
1552
+ }
1553
+
1554
+ points.getPoint(innerPoly[d], p0);
1555
+ subtract(p2, p0, v2);
1556
+ l2 = dot(v2, v2);
1557
+
1558
+ if (l2 > 0) {
1559
+ q = dot(v1, v2);
1560
+ q *= q / l2;
1561
+
1562
+ if (q > qmax) {
1563
+ qmax = q;
1564
+ }
1565
+ }
1566
+
1567
+ if (l1 > 0) {
1568
+ return qmax / l1; // also l1 + qmax, incorporates distance;
1569
+ }
1570
+
1571
+ return Number.MAX_VALUE;
1572
+ } // ---------------------------------------------------
1573
+
1574
+ /**
1575
+ * Find the two sharpest verts on an inner (i.e. inside-out) poly.
1576
+ *
1577
+ * @param {Array} poly
1578
+ * @param {vtkPoints} points
1579
+ * @param {Vector3} normal
1580
+ * @param {[Number, Number]} verts
1581
+ */
1582
+
1583
+ function vtkCCSFindSharpestVerts(poly, points, normal, verts) {
1584
+ var p1 = [];
1585
+ var p2 = [];
1586
+ var v1 = [];
1587
+ var v2 = [];
1588
+ var v = [];
1589
+ var l1;
1590
+ var l2;
1591
+ var minVal = [0, 0];
1592
+ verts[0] = 0;
1593
+ verts[1] = 0;
1594
+ var n = poly.length;
1595
+ points.getPoint(poly[n - 1], p2);
1596
+ points.getPoint(poly[0], p1);
1597
+ subtract(p1, p2, v1);
1598
+ l1 = Math.sqrt(dot(v1, v1));
1599
+
1600
+ for (var j = 0; j < n; j++) {
1601
+ var k = j + 1;
1602
+
1603
+ if (k === n) {
1604
+ k = 0;
1605
+ }
1606
+
1607
+ points.getPoint(poly[k], p2);
1608
+ subtract(p2, p1, v2);
1609
+ l2 = Math.sqrt(dot(v2, v2));
1610
+ cross(v1, v2, v);
1611
+ var b = dot(v, normal);
1612
+
1613
+ if (b < 0 && l1 * l2 > 0) {
1614
+ // Dot product is |v1||v2|cos(theta), range [-1, +1]
1615
+ var val = dot(v1, v2) / (l1 * l2);
1616
+
1617
+ if (val < minVal[0]) {
1618
+ minVal[1] = minVal[0];
1619
+ minVal[0] = val;
1620
+ verts[1] = verts[0];
1621
+ verts[0] = j;
1622
+ }
1623
+ } // Rotate to the next point
1624
+
1625
+
1626
+ p1[0] = p2[0];
1627
+ p1[1] = p2[1];
1628
+ p1[2] = p2[2];
1629
+ v1[0] = v2[0];
1630
+ v1[1] = v2[1];
1631
+ v1[2] = v2[2];
1632
+ l1 = l2;
1633
+ }
1634
+ } // ---------------------------------------------------
1635
+
1636
+ /**
1637
+ * Find two valid cuts between outerPoly and innerPoly.
1638
+ * Used by vtkCCSCutHoleyPolys.
1639
+ *
1640
+ * @param {Array} polys
1641
+ * @param {Array} polyGroup
1642
+ * @param {Number} outerPolyId
1643
+ * @param {Number} innerPolyId
1644
+ * @param {vtkPoints} points
1645
+ * @param {Vector3} normal
1646
+ * @param {Array[]} cuts
1647
+ * @param {Boolean} exhaustive
1648
+ */
1649
+
1650
+ function vtkCCSFindCuts(polys, polyGroup, outerPolyId, innerPolyId, points, normal, cuts, exhaustive) {
1651
+ var outerPoly = polys[outerPolyId];
1652
+ var innerPoly = polys[innerPolyId];
1653
+ var innerSize = innerPoly.length; // Find the two sharpest points on the inner poly
1654
+
1655
+ var verts = [];
1656
+ vtkCCSFindSharpestVerts(innerPoly, points, normal, verts); // A list of cut locations according to quality
1657
+
1658
+ var cutlist = [];
1659
+ cutlist.length = outerPoly.length; // Search for potential cuts (need to find two cuts)
1660
+
1661
+ var cutId = 0;
1662
+ cuts[0][0] = 0;
1663
+ cuts[0][1] = 0;
1664
+ cuts[1][0] = 0;
1665
+ cuts[1][1] = 0;
1666
+ var foundCut = false;
1667
+
1668
+ for (cutId = 0; cutId < 2; cutId++) {
1669
+ var count = exhaustive ? innerSize : 3;
1670
+
1671
+ for (var i = 0; i < count && !foundCut; i++) {
1672
+ // Semi-randomize the search order
1673
+ // TODO: Does this do the same as in C++?
1674
+ // eslint-disable-next-line no-bitwise
1675
+ var j = (i >> 1) + (i & 1) * (innerSize + 1 >> 1); // Start at the best first point
1676
+
1677
+ j = (j + verts[cutId]) % innerSize;
1678
+
1679
+ for (var kk = 0; kk < outerPoly.length; kk++) {
1680
+ var q = vtkCCSCutQuality(outerPoly, innerPoly, kk, j, points);
1681
+ cutlist[kk] = [q, kk];
1682
+ }
1683
+
1684
+ cutlist.sort(function (a, b) {
1685
+ return a[0] - b[0];
1686
+ });
1687
+
1688
+ for (var lid = 0; lid < cutlist.length; lid++) {
1689
+ var k = cutlist[lid][1]; // If this is the second cut, do extra checks
1690
+
1691
+ if (cutId > 0) {
1692
+ // Make sure cuts don't share an endpoint
1693
+ if (j === cuts[0][1] || k === cuts[0][0]) {
1694
+ // eslint-disable-next-line no-continue
1695
+ continue;
1696
+ } // Make sure cuts don't intersect
1697
+
1698
+
1699
+ var p1 = [];
1700
+ var p2 = [];
1701
+ points.getPoint(outerPoly[cuts[0][0]], p1);
1702
+ points.getPoint(innerPoly[cuts[0][1]], p2);
1703
+ var q1 = [];
1704
+ var q2 = [];
1705
+ points.getPoint(outerPoly[k], q1);
1706
+ points.getPoint(innerPoly[j], q2);
1707
+ var u = void 0;
1708
+ var v = void 0;
1709
+
1710
+ if (vtkLine.intersection(p1, p2, q1, q2, u, v) === vtkLine.IntersectionState.YES_INTERSECTION) {
1711
+ // eslint-disable-next-line no-continue
1712
+ continue;
1713
+ }
1714
+ } // This check is done for both cuts
1715
+
1716
+
1717
+ if (vtkCCSCheckCut(polys, points, normal, polyGroup, outerPolyId, innerPolyId, k, j)) {
1718
+ cuts[cutId][0] = k;
1719
+ cuts[cutId][1] = j;
1720
+ foundCut = true;
1721
+ break;
1722
+ }
1723
+ }
1724
+ }
1725
+
1726
+ if (!foundCut) {
1727
+ return false;
1728
+ }
1729
+ }
1730
+
1731
+ return true;
1732
+ } // ---------------------------------------------------
1733
+
1734
+ /**
1735
+ * Helper for vtkCCSCutHoleyPolys. Change a polygon and a hole
1736
+ * into two separate polygons by making two cuts between them.
1737
+ *
1738
+ * @param {Array[]} polys
1739
+ * @param {Array} polyEdges
1740
+ * @param {Number} outerPolyId
1741
+ * @param {Number} innerPolyId
1742
+ * @param {vtkPoints} points
1743
+ * @param {Array[]} cuts
1744
+ */
1745
+
1746
+ function vtkCCSMakeCuts(polys, polyEdges, outerPolyId, innerPolyId, points, cuts) {
1747
+ var q = [];
1748
+ var r = [];
1749
+
1750
+ for (var bb = 0; bb < 2; bb++) {
1751
+ var ptId1 = polys[outerPolyId][cuts[bb][0]];
1752
+ var ptId2 = polys[innerPolyId][cuts[bb][1]];
1753
+ points.getPoint(ptId1, q);
1754
+ points.getPoint(ptId2, r);
1755
+ }
1756
+
1757
+ var outerPoly = polys[outerPolyId];
1758
+ var innerPoly = polys[innerPolyId];
1759
+ var outerEdges = polyEdges[outerPolyId];
1760
+ var innerEdges = polyEdges[innerPolyId]; // Generate new polys from the cuts
1761
+
1762
+ var n = outerPoly.length;
1763
+ var m = innerPoly.length;
1764
+ var idx; // Generate poly1
1765
+
1766
+ var n1 = n * (cuts[1][0] < cuts[0][0]) + cuts[1][0] - cuts[0][0] + 1;
1767
+ var n2 = n1 + m * (cuts[0][1] < cuts[1][1]) + cuts[0][1] - cuts[1][1] + 1;
1768
+ var poly1 = [];
1769
+ poly1.length = n2;
1770
+ var edges1 = new Array(n2);
1771
+ idx = cuts[0][0];
1772
+
1773
+ for (var i1 = 0; i1 < n1; i1++) {
1774
+ var k = idx++;
1775
+ poly1[i1] = outerPoly[k];
1776
+ edges1[i1] = outerEdges[k];
1777
+ idx *= idx !== n;
1778
+ }
1779
+
1780
+ edges1[n1 - 1] = -1;
1781
+ idx = cuts[1][1];
1782
+
1783
+ for (var i2 = n1; i2 < n2; i2++) {
1784
+ var _k2 = idx++;
1785
+
1786
+ poly1[i2] = innerPoly[_k2];
1787
+ edges1[i2] = innerEdges[_k2];
1788
+ idx *= idx !== m;
1789
+ }
1790
+
1791
+ edges1[n2 - 1] = -1; // Generate poly2
1792
+
1793
+ var m1 = n * (cuts[0][0] < cuts[1][0]) + cuts[0][0] - cuts[1][0] + 1;
1794
+ var m2 = m1 + m * (cuts[1][1] < cuts[0][1]) + cuts[1][1] - cuts[0][1] + 1;
1795
+ var poly2 = [];
1796
+ poly2.length = m2;
1797
+ var edges2 = new Array(m2);
1798
+ idx = cuts[1][0];
1799
+
1800
+ for (var j1 = 0; j1 < m1; j1++) {
1801
+ var _k3 = idx++;
1802
+
1803
+ poly2[j1] = outerPoly[_k3];
1804
+ edges2[j1] = outerEdges[_k3];
1805
+ idx *= idx !== n;
1806
+ }
1807
+
1808
+ edges2[m1 - 1] = -1;
1809
+ idx = cuts[0][1];
1810
+
1811
+ for (var j2 = m1; j2 < m2; j2++) {
1812
+ var _k4 = idx++;
1813
+
1814
+ poly2[j2] = innerPoly[_k4];
1815
+ edges2[j2] = innerEdges[_k4];
1816
+ idx *= idx !== m;
1817
+ }
1818
+
1819
+ edges2[m2 - 1] = -1; // Replace outerPoly and innerPoly with these new polys
1820
+
1821
+ polys[outerPolyId] = poly1;
1822
+ polys[innerPolyId] = poly2;
1823
+ polyEdges[outerPolyId] = edges1;
1824
+ polyEdges[innerPolyId] = edges2;
1825
+ } // ---------------------------------------------------
1826
+
1827
+ /**
1828
+ * After the holes have been identified, make cuts between the
1829
+ * outer poly and each hole. Make two cuts per hole. The only
1830
+ * strict requirement is that the cut must not intersect any
1831
+ * edges, but it's best to make sure that no really sharp angles
1832
+ * are created.
1833
+ *
1834
+ * @param {Array[]} polys
1835
+ * @param {vtkPoints} points
1836
+ * @param {Array[]} polyGroups
1837
+ * @param {Array} polyEdges
1838
+ * @param {Vector3} normal
1839
+ * @returns {boolean}
1840
+ */
1841
+
1842
+ function vtkCCSCutHoleyPolys(polys, points, polyGroups, polyEdges, normal) {
1843
+ var cutFailure = 0; // Go through all groups and cut out the first inner poly that is
1844
+ // found. Every time an inner poly is cut out, the groupId counter
1845
+ // is reset because cutting a poly creates a new group.
1846
+
1847
+ var groupId = 0;
1848
+
1849
+ while (groupId < polyGroups.length) {
1850
+ var polyGroup = polyGroups[groupId]; // Only need to make a cut if the group size is greater than 1
1851
+
1852
+ if (polyGroup.length > 1) {
1853
+ // The first member of the group is the outer poly
1854
+ var outerPolyId = polyGroup[0]; // The second member of the group is the first inner poly
1855
+
1856
+ var innerPolyId = polyGroup[1]; // Sort the group by size, do largest holes first
1857
+
1858
+ var innerBySize = new Array(polyGroup.length);
1859
+
1860
+ for (var i = 1; i < polyGroup.length; i++) {
1861
+ innerBySize[i] = [polys[polyGroup[i]].length, i];
1862
+ }
1863
+
1864
+ innerBySize = [innerBySize[0]].concat(_toConsumableArray(innerBySize.splice(1).sort(function (a, b) {
1865
+ return a[0] - b[0];
1866
+ })));
1867
+ reverseElements(innerBySize, 1, innerBySize.length - 1); // Need to check all inner polys in sequence, until one succeeds.
1868
+ // Do a quick search first, then do an exhaustive search.
1869
+
1870
+ var madeCut = 0;
1871
+ var inner = 0;
1872
+
1873
+ for (var exhaustive = 0; exhaustive < 2 && !madeCut; exhaustive++) {
1874
+ for (var j = 1; j < polyGroup.length; j++) {
1875
+ inner = innerBySize[j][1];
1876
+ innerPolyId = polyGroup[inner];
1877
+ var cuts = [];
1878
+
1879
+ if (vtkCCSFindCuts(polys, polyGroup, outerPolyId, innerPolyId, points, normal, cuts, exhaustive)) {
1880
+ vtkCCSMakeCuts(polys, polyEdges, outerPolyId, innerPolyId, points, cuts);
1881
+ madeCut = 1;
1882
+ break;
1883
+ }
1884
+ }
1885
+ }
1886
+
1887
+ if (madeCut) {
1888
+ // Move successfully cut innerPolyId into its own group
1889
+ polyGroup.splice(inner, 1); // Only add if innerPolyId hasn't been set already.
1890
+ // Having the same poly occur as both polyGroup and
1891
+ // innerPoly would cause an infinite loop.
1892
+
1893
+ if (polyGroups[innerPolyId].length === 0) {
1894
+ polyGroups[innerPolyId].push(innerPolyId);
1895
+ }
1896
+ } else {
1897
+ // Remove all failed inner polys from the group
1898
+ for (var k = 1; k < polyGroup.length; k++) {
1899
+ innerPolyId = polyGroup[k]; // Only add if innerPolyId hasn't been set already.
1900
+ // Having the same poly occur as both polyGroup and
1901
+ // innerPoly would cause an infinite loop.
1902
+
1903
+ if (polyGroups[innerPolyId].length === 0) {
1904
+ polyGroups[innerPolyId].push(innerPolyId);
1905
+ }
1906
+ }
1907
+
1908
+ polyGroup.length = 1;
1909
+ cutFailure = 1;
1910
+ } // If there are other interior polys in the group, find out whether
1911
+ // they are in poly1 or poly2
1912
+
1913
+
1914
+ if (polyGroup.length > 1) {
1915
+ var poly1 = polys[outerPolyId];
1916
+ var pp = new Float64Array(3 * poly1.length);
1917
+ var bounds = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0];
1918
+ var tol2 = vtkCCSPrepareForPolyInPoly(poly1, points, pp, bounds);
1919
+ var nextGroupId = groupId;
1920
+ var ii = 1;
1921
+
1922
+ while (ii < polyGroup.length) {
1923
+ if (vtkCCSPolyInPoly(poly1, polys[polyGroup[ii]], points, normal, pp, bounds, tol2)) {
1924
+ // Keep this poly in polyGroup
1925
+ ii++;
1926
+ } else {
1927
+ // Move this poly to poly2 group
1928
+ polyGroups[innerPolyId].push(polyGroup[ii]);
1929
+ polyGroup.splice(ii, 1); // Reduce the groupId to ensure that this new group will get cut
1930
+
1931
+ if (innerPolyId < nextGroupId) {
1932
+ nextGroupId = innerPolyId;
1933
+ }
1934
+ }
1935
+ } // Set the groupId for the next iteration
1936
+
1937
+
1938
+ groupId = nextGroupId; // eslint-disable-next-line no-continue
1939
+
1940
+ continue;
1941
+ }
1942
+ } // Increment to the next group
1943
+
1944
+
1945
+ groupId++;
1946
+ }
1947
+
1948
+ return !cutFailure;
1949
+ }
1950
+
1951
+ export { reverseElements, vtkCCSCheckCut, vtkCCSCheckPolygonSense, vtkCCSCutHoleyPolys, vtkCCSCutQuality, vtkCCSFindCuts, vtkCCSFindSharpestVerts, vtkCCSFindTrueEdges, vtkCCSInsertTriangle, vtkCCSJoinLooseEnds, vtkCCSMakeCuts, vtkCCSMakeHoleyPolys, vtkCCSMakePolysFromLines, vtkCCSPolyInPoly, vtkCCSPrepareForPolyInPoly, vtkCCSReversePoly, vtkCCSSplitAtPinchPoints, vtkCCSTriangleQuality, vtkCCSTriangulate, vtkCCSVectorProgression };