@kitware/vtk.js 23.4.3 → 24.0.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 (144) hide show
  1. package/BREAKING_CHANGES.md +33 -0
  2. package/Common/Core/DataArray.js +4 -0
  3. package/Common/Core/Math/index.js +2 -2
  4. package/Common/Core/Math.js +1 -1
  5. package/Common/DataModel/DataSetAttributes/FieldData.js +9 -5
  6. package/Common/DataModel/ImageData.d.ts +23 -6
  7. package/Common/DataModel/ImageData.js +8 -1
  8. package/Common/DataModel/PolyData.d.ts +8 -1
  9. package/Common/DataModel/PolyData.js +5 -3
  10. package/Common/DataModel/Triangle.js +217 -2
  11. package/Common/Transform/LandmarkTransform.js +1 -1
  12. package/Filters/General/OBBTree/OBBNode.js +82 -0
  13. package/Filters/General/OBBTree/helper.js +92 -0
  14. package/Filters/General/OBBTree.js +1249 -0
  15. package/Filters/General/WindowedSincPolyDataFilter.js +1 -1
  16. package/Filters/General.js +2 -0
  17. package/Filters/Sources/CircleSource.js +1 -1
  18. package/Filters/Sources/PointSource.js +1 -1
  19. package/Filters/Texture/TextureMapToPlane.js +1 -1
  20. package/Interaction/Manipulators/KeyboardCameraManipulator.js +1 -1
  21. package/Interaction/Manipulators/MouseCameraTrackballRollManipulator.js +1 -1
  22. package/Interaction/Manipulators/MouseCameraTrackballRotateManipulator.js +1 -1
  23. package/Interaction/Manipulators/MouseCameraUnicamManipulator.js +1 -1
  24. package/Interaction/Manipulators/MouseCameraUnicamRotateManipulator.js +1 -1
  25. package/Interaction/Style/InteractorStyleImage.js +3 -3
  26. package/Interaction/Style/InteractorStyleMPRSlice.js +12 -6
  27. package/Interaction/Style/InteractorStyleManipulator.js +42 -28
  28. package/Interaction/Style/InteractorStyleRemoteMouse.js +32 -14
  29. package/Interaction/Style/InteractorStyleTrackballCamera.js +7 -7
  30. package/Interaction/Widgets/OrientationMarkerWidget.js +18 -13
  31. package/Interaction/Widgets/PiecewiseGaussianWidget.js +1 -1
  32. package/Interaction/Widgets.js +1 -35
  33. package/Proxy/Core/View2DProxy.js +1 -1
  34. package/Rendering/Core/ColorTransferFunction.js +1 -1
  35. package/Rendering/Core/Coordinate.js +1 -1
  36. package/Rendering/Core/CubeAxesActor.js +1 -1
  37. package/Rendering/Core/Glyph3DMapper.js +1 -1
  38. package/Rendering/Core/ImageMapper.js +1 -1
  39. package/Rendering/Core/InteractorObserver.js +11 -10
  40. package/Rendering/Core/InteractorStyle.js +9 -4
  41. package/Rendering/Core/Mapper.js +1 -1
  42. package/Rendering/Core/Prop.js +6 -4
  43. package/Rendering/Core/Prop3D.js +1 -1
  44. package/Rendering/Core/RenderWindowInteractor.js +24 -17
  45. package/Rendering/Core/Renderer.js +24 -19
  46. package/Rendering/Core/ScalarBarActor.js +1 -1
  47. package/Rendering/Core/Viewport.js +1 -1
  48. package/Rendering/Core/VolumeMapper.js +1 -1
  49. package/Rendering/OpenGL/Actor.js +2 -2
  50. package/Rendering/OpenGL/Actor2D.js +2 -2
  51. package/Rendering/OpenGL/BufferObject.js +6 -5
  52. package/Rendering/OpenGL/Camera.js +3 -3
  53. package/Rendering/OpenGL/CellArrayBufferObject.js +1 -1
  54. package/Rendering/OpenGL/Framebuffer.js +13 -12
  55. package/Rendering/OpenGL/Glyph3DMapper.js +10 -8
  56. package/Rendering/OpenGL/HardwareSelector.js +35 -25
  57. package/Rendering/OpenGL/ImageMapper.js +51 -45
  58. package/Rendering/OpenGL/ImageSlice.js +2 -2
  59. package/Rendering/OpenGL/PixelSpaceCallbackMapper.js +4 -2
  60. package/Rendering/OpenGL/PolyDataMapper.js +14 -11
  61. package/Rendering/OpenGL/PolyDataMapper2D.js +7 -6
  62. package/Rendering/OpenGL/Renderer.js +11 -7
  63. package/Rendering/OpenGL/ReplacementShaderMapper.js +1 -1
  64. package/Rendering/OpenGL/ScalarBarActor.js +2 -2
  65. package/Rendering/OpenGL/ShaderCache.js +7 -5
  66. package/Rendering/OpenGL/Skybox.js +11 -9
  67. package/Rendering/OpenGL/SphereMapper.js +2 -2
  68. package/Rendering/OpenGL/StickMapper.js +2 -2
  69. package/Rendering/OpenGL/SurfaceLIC/LineIntegralConvolution2D/pingpong.js +13 -12
  70. package/Rendering/OpenGL/SurfaceLIC/LineIntegralConvolution2D.js +11 -9
  71. package/Rendering/OpenGL/SurfaceLIC/SurfaceLICInterface.js +19 -12
  72. package/Rendering/OpenGL/SurfaceLIC/SurfaceLICMapper.js +9 -6
  73. package/Rendering/OpenGL/Texture.js +44 -31
  74. package/Rendering/OpenGL/VertexArrayObject.js +7 -7
  75. package/Rendering/OpenGL/Volume.js +3 -2
  76. package/Rendering/OpenGL/VolumeMapper.js +30 -26
  77. package/Rendering/OpenGL/glsl/vtkVolumeFS.glsl.js +1 -1
  78. package/Rendering/SceneGraph/ViewNode.js +8 -7
  79. package/Rendering/WebGPU/Renderer.js +18 -10
  80. package/Widgets/Core/AbstractWidget.js +5 -4
  81. package/Widgets/Core/AbstractWidgetFactory.js +2 -1
  82. package/Widgets/Core/WidgetManager.js +66 -49
  83. package/Widgets/Manipulators/LineManipulator.js +1 -1
  84. package/Widgets/Representations/CircleContextRepresentation.js +1 -1
  85. package/Widgets/Representations/ImplicitPlaneRepresentation.js +5 -5
  86. package/Widgets/Representations/PolyLineRepresentation.js +1 -1
  87. package/Widgets/Representations/ResliceCursorContextRepresentation.js +7 -7
  88. package/Widgets/SVG/SVGLandmarkRepresentation/Constants.js +2 -2
  89. package/Widgets/SVG/SVGLandmarkRepresentation.js +21 -8
  90. package/Widgets/SVG/SVGRepresentation.js +1 -1
  91. package/Widgets/Widgets3D/AngleWidget/behavior.js +14 -6
  92. package/Widgets/Widgets3D/DistanceWidget/behavior.js +14 -6
  93. package/Widgets/Widgets3D/EllipseWidget.js +0 -1
  94. package/Widgets/Widgets3D/ImageCroppingWidget/behavior.js +6 -2
  95. package/Widgets/Widgets3D/ImplicitPlaneWidget.js +4 -2
  96. package/Widgets/Widgets3D/LabelWidget/behavior.js +138 -0
  97. package/Widgets/Widgets3D/LabelWidget/state.js +22 -0
  98. package/Widgets/Widgets3D/LabelWidget.js +79 -0
  99. package/Widgets/Widgets3D/LineWidget/behavior.js +18 -9
  100. package/Widgets/Widgets3D/LineWidget/helpers.js +1 -1
  101. package/Widgets/Widgets3D/LineWidget.js +0 -1
  102. package/Widgets/Widgets3D/PaintWidget/behavior.js +5 -3
  103. package/Widgets/Widgets3D/PolyLineWidget/behavior.js +18 -8
  104. package/Widgets/Widgets3D/RectangleWidget.js +0 -1
  105. package/Widgets/Widgets3D/ResliceCursorWidget/behavior.js +1 -1
  106. package/Widgets/Widgets3D/ResliceCursorWidget/helpers.js +1 -1
  107. package/Widgets/Widgets3D/ResliceCursorWidget.js +1 -1
  108. package/Widgets/Widgets3D/ShapeWidget/behavior.js +18 -11
  109. package/Widgets/Widgets3D/SplineWidget/behavior.js +33 -21
  110. package/interfaces.d.ts +11 -0
  111. package/macros.d.ts +26 -1
  112. package/macros.js +51 -19
  113. package/package.json +1 -1
  114. package/types.d.ts +1 -0
  115. package/Interaction/Widgets/AbstractWidget.js +0 -104
  116. package/Interaction/Widgets/DistanceRepresentation.js +0 -116
  117. package/Interaction/Widgets/DistanceWidget.js +0 -77
  118. package/Interaction/Widgets/HandleRepresentation/Constants.js +0 -12
  119. package/Interaction/Widgets/HandleRepresentation.js +0 -100
  120. package/Interaction/Widgets/HandleWidget/Constants.js +0 -9
  121. package/Interaction/Widgets/HandleWidget.js +0 -194
  122. package/Interaction/Widgets/ImageCroppingRegionsRepresentation.js +0 -233
  123. package/Interaction/Widgets/ImageCroppingRegionsWidget/Constants.js +0 -16
  124. package/Interaction/Widgets/ImageCroppingRegionsWidget.js +0 -573
  125. package/Interaction/Widgets/LabelRepresentation/Constants.js +0 -17
  126. package/Interaction/Widgets/LabelRepresentation.js +0 -325
  127. package/Interaction/Widgets/LabelWidget.js +0 -65
  128. package/Interaction/Widgets/LineRepresentation/Constants.js +0 -21
  129. package/Interaction/Widgets/LineRepresentation.js +0 -498
  130. package/Interaction/Widgets/LineWidget/Constants.js +0 -11
  131. package/Interaction/Widgets/LineWidget.js +0 -296
  132. package/Interaction/Widgets/PointPlacer.js +0 -51
  133. package/Interaction/Widgets/ResliceCursor/ResliceCursor/Constants.js +0 -10
  134. package/Interaction/Widgets/ResliceCursor/ResliceCursor.js +0 -269
  135. package/Interaction/Widgets/ResliceCursor/ResliceCursorActor/Constants.js +0 -10
  136. package/Interaction/Widgets/ResliceCursor/ResliceCursorActor.js +0 -146
  137. package/Interaction/Widgets/ResliceCursor/ResliceCursorLineRepresentation.js +0 -332
  138. package/Interaction/Widgets/ResliceCursor/ResliceCursorPolyDataAlgorithm.js +0 -134
  139. package/Interaction/Widgets/ResliceCursor/ResliceCursorRepresentation/Constants.js +0 -16
  140. package/Interaction/Widgets/ResliceCursor/ResliceCursorRepresentation.js +0 -371
  141. package/Interaction/Widgets/ResliceCursor/ResliceCursorWidget/Constants.js +0 -10
  142. package/Interaction/Widgets/ResliceCursor/ResliceCursorWidget.js +0 -157
  143. package/Interaction/Widgets/SphereHandleRepresentation.js +0 -370
  144. package/Interaction/Widgets/WidgetRepresentation.js +0 -121
@@ -0,0 +1,1249 @@
1
+ import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
2
+ import macro from '../../macros.js';
3
+ import vtkCellArray from '../../Common/Core/CellArray.js';
4
+ import vtkLine from '../../Common/DataModel/Line.js';
5
+ import { d as dot, j as cross, n as norm, t as jacobi, l as normalize, k as add } from '../../Common/Core/Math/index.js';
6
+ import vtkMatrixBuilder from '../../Common/Core/MatrixBuilder.js';
7
+ import vtkOBBNode from './OBBTree/OBBNode.js';
8
+ import vtkPoints from '../../Common/Core/Points.js';
9
+ import { CellType } from '../../Common/DataModel/CellTypes/Constants.js';
10
+ import vtkPolyData from '../../Common/DataModel/PolyData.js';
11
+ import vtkTriangle from '../../Common/DataModel/Triangle.js';
12
+ import { pushArray, getCellTriangles } from './OBBTree/helper.js';
13
+ import { mat4, vec4 } from 'gl-matrix';
14
+
15
+ var vtkErrorMacro = macro.vtkErrorMacro;
16
+ var VTK_DOUBLE_MAX = Number.MAX_SAFE_INTEGER; // ----------------------------------------------------------------------------
17
+ // vtkOBBTree methods
18
+ // ----------------------------------------------------------------------------
19
+
20
+ function vtkOBBTree(publicAPI, model) {
21
+ // Set our classname
22
+ model.classHierarchy.push('vtkOBBTree');
23
+ /**
24
+ * Compute an OBB from the list of cells given. This used to be
25
+ * public but should not have been. A public call has been added
26
+ * so that the functionality can be accessed.
27
+ * @param {Array} cells
28
+ * @param {Array[3]} corner
29
+ * @param {Array[3]} max
30
+ * @param {Array[3]} mid
31
+ * @param {Array[3]} min
32
+ * @param {Array[3]} size
33
+ */
34
+
35
+ function computeOBB(cells, corner, max, mid, min, size) {
36
+ model.OBBCount++;
37
+ model.pointsList = []; //
38
+ // Compute mean & moments
39
+ //
40
+
41
+ var numCells = cells.length;
42
+ var mean = [0, 0, 0];
43
+ var totMass = 0.0;
44
+ var a0 = [0, 0, 0];
45
+ var a1 = [0, 0, 0];
46
+ var a2 = [0, 0, 0];
47
+ var a = [a0, a1, a2];
48
+ var dp0 = [0, 0, 0];
49
+ var dp1 = [0, 0, 0];
50
+ var c = [0, 0, 0];
51
+ var triMass = 0;
52
+
53
+ if (!model.dataset.getCells()) {
54
+ model.dataset.buildCells();
55
+ }
56
+
57
+ for (var i = 0; i < numCells; i++) {
58
+ var cellId = cells[i];
59
+ var type = model.dataset.getCells().getCellType(cellId);
60
+ var ptIds = model.dataset.getCellPoints(cellId).cellPointIds;
61
+ var _numPts = ptIds.length;
62
+
63
+ for (var j = 0; j < _numPts - 2; j++) {
64
+ var cellsIds = getCellTriangles(ptIds, type, j);
65
+ var pId = cellsIds.ptId0;
66
+ var qId = cellsIds.ptId1;
67
+ var rId = cellsIds.ptId2;
68
+
69
+ if (pId < 0) {
70
+ // eslint-disable-next-line no-continue
71
+ continue;
72
+ }
73
+
74
+ var p = [];
75
+ var q = [];
76
+ var r = [];
77
+ model.dataset.getPoints().getPoint(pId, p);
78
+ model.dataset.getPoints().getPoint(qId, q);
79
+ model.dataset.getPoints().getPoint(rId, r); // p, q, and r are the oriented triangle points.
80
+ // Compute the components of the moment of inertia tensor.
81
+
82
+ for (var k = 0; k < 3; k++) {
83
+ // two edge vectors
84
+ dp0[k] = q[k] - p[k];
85
+ dp1[k] = r[k] - p[k]; // centroid
86
+
87
+ c[k] = (p[k] + q[k] + r[k]) / 3;
88
+ }
89
+
90
+ var xp = cross(dp0, dp1, []);
91
+ triMass = 0.5 * norm(xp);
92
+ totMass += triMass;
93
+
94
+ for (var _k = 0; _k < 3; _k++) {
95
+ mean[_k] += triMass * c[_k];
96
+ } // on-diagonal terms
97
+
98
+
99
+ a0[0] += triMass * (9 * c[0] * c[0] + p[0] * p[0] + q[0] * q[0] + r[0] * r[0]) / 12;
100
+ a1[1] += triMass * (9 * c[1] * c[1] + p[1] * p[1] + q[1] * q[1] + r[1] * r[1]) / 12;
101
+ a2[2] += triMass * (9 * c[2] * c[2] + p[2] * p[2] + q[2] * q[2] + r[2] * r[2]) / 12; // off-diagonal terms
102
+
103
+ a0[1] += triMass * (9 * c[0] * c[1] + p[0] * p[1] + q[0] * q[1] + r[0] * r[1]) / 12;
104
+ a0[2] += triMass * (9 * c[0] * c[2] + p[0] * p[2] + q[0] * q[2] + r[0] * r[2]) / 12;
105
+ a1[2] += triMass * (9 * c[1] * c[2] + p[1] * p[2] + q[1] * q[2] + r[1] * r[2]) / 12;
106
+ } // end foreach triangle
107
+ // While computing cell moments, gather all the cell's
108
+ // point coordinates into a single list.
109
+
110
+
111
+ for (var _j = 0; _j < _numPts; _j++) {
112
+ if (model.insertedPoints[ptIds[_j]] !== model.OBBCount) {
113
+ model.insertedPoints[ptIds[_j]] = model.OBBCount;
114
+ var pt = [];
115
+ model.dataset.getPoints().getPoint(ptIds[_j], pt);
116
+ model.pointsList.push(pt);
117
+ }
118
+ } // for all points of this cell
119
+
120
+ } // end foreach cell
121
+ // normalize data
122
+
123
+
124
+ for (var _i = 0; _i < 3; _i++) {
125
+ mean[_i] /= totMass;
126
+ } // matrix is symmetric
127
+
128
+
129
+ a1[0] = a0[1];
130
+ a2[0] = a0[2];
131
+ a2[1] = a1[2]; // get covariance from moments
132
+
133
+ for (var _i2 = 0; _i2 < 3; _i2++) {
134
+ for (var _j2 = 0; _j2 < 3; _j2++) {
135
+ a[_i2][_j2] = a[_i2][_j2] / totMass - mean[_i2] * mean[_j2]; // send to zero if close to zero
136
+
137
+ if (Math.abs(a[_i2][_j2]) < 1e-12) {
138
+ a[_i2][_j2] = 0;
139
+ }
140
+ }
141
+ } //
142
+ // Extract axes (i.e., eigenvectors) from covariance matrix.
143
+ //
144
+
145
+
146
+ var v0 = [0, 0, 0];
147
+ var v1 = [0, 0, 0];
148
+ var v2 = [0, 0, 0];
149
+ var v = [v0, v1, v2];
150
+ jacobi(a, size, v);
151
+ max[0] = v[0][0];
152
+ max[1] = v[1][0];
153
+ max[2] = v[2][0];
154
+ mid[0] = v[0][1];
155
+ mid[1] = v[1][1];
156
+ mid[2] = v[2][1];
157
+ min[0] = v[0][2];
158
+ min[1] = v[1][2];
159
+ min[2] = v[2][2];
160
+
161
+ for (var _i3 = 0; _i3 < 3; _i3++) {
162
+ a[0][_i3] = mean[_i3] + max[_i3];
163
+ a[1][_i3] = mean[_i3] + mid[_i3];
164
+ a[2][_i3] = mean[_i3] + min[_i3];
165
+ } //
166
+ // Create oriented bounding box by projecting points onto eigenvectors.
167
+ //
168
+
169
+
170
+ var tMin = [VTK_DOUBLE_MAX, VTK_DOUBLE_MAX, VTK_DOUBLE_MAX];
171
+ var tMax = [-VTK_DOUBLE_MAX, -VTK_DOUBLE_MAX, -VTK_DOUBLE_MAX];
172
+ var numPts = model.pointsList.length;
173
+
174
+ for (var ptId = 0; ptId < numPts; ptId++) {
175
+ var _p = model.pointsList[ptId];
176
+
177
+ for (var _i4 = 0; _i4 < 3; _i4++) {
178
+ var out = vtkLine.distanceToLine(_p, mean, a[_i4], []);
179
+
180
+ if (out.t < tMin[_i4]) {
181
+ tMin[_i4] = out.t;
182
+ }
183
+
184
+ if (out.t > tMax[_i4]) {
185
+ tMax[_i4] = out.t;
186
+ }
187
+ }
188
+ } // for all points
189
+
190
+
191
+ for (var _i5 = 0; _i5 < 3; _i5++) {
192
+ corner[_i5] = mean[_i5] + tMin[0] * max[_i5] + tMin[1] * mid[_i5] + tMin[2] * min[_i5];
193
+ max[_i5] *= tMax[0] - tMin[0];
194
+ mid[_i5] *= tMax[1] - tMin[1];
195
+ min[_i5] *= tMax[2] - tMin[2];
196
+ }
197
+ }
198
+ /**
199
+ * Build the OBB tree
200
+ * @param {Array} cells
201
+ * @param {vtkOBBNode} obbNode
202
+ * @param {Number} level
203
+ */
204
+
205
+
206
+ function buildTree(cells, obbNode, level) {
207
+ var numCells = cells.length;
208
+
209
+ if (level > model.level) {
210
+ model.level = level;
211
+ }
212
+
213
+ var axes = obbNode.getAxes();
214
+ var corner = obbNode.getCorner();
215
+ var size = [0, 0, 0];
216
+ computeOBB(cells, corner, axes[0], axes[1], axes[2], size);
217
+ obbNode.setAxes(axes);
218
+ obbNode.setCorner(corner); // Check whether to continue recursing; if so, create two children and
219
+ // assign cells to appropriate child.
220
+
221
+ if (level < model.maxLevel && numCells > model.numberOfCellsPerNode) {
222
+ var LHlist = [];
223
+ var RHlist = [];
224
+ var p = [0, 0, 0];
225
+ var n = [0, 0, 0]; // loop over three split planes to find acceptable one
226
+
227
+ for (var i = 0; i < 3; i++) {
228
+ // compute split point
229
+ p[i] = corner[i] + axes[0][i] / 2 + axes[1][i] / 2 + axes[2][i] / 2;
230
+ }
231
+
232
+ var splitPlane = 0;
233
+ var splitAcceptable = 0;
234
+ var bestRatio = 1;
235
+ var foundBestSplit = 0;
236
+ var bestPlane = 0;
237
+
238
+ for (; !splitAcceptable && splitPlane < 3;) {
239
+ // compute split normal
240
+ for (var _i6 = 0; _i6 < 3; _i6++) {
241
+ n[_i6] = axes[splitPlane][_i6];
242
+ }
243
+
244
+ normalize(n); // traverse cells, assigning to appropriate child list as necessary
245
+
246
+ var _loop = function _loop(_i7) {
247
+ var cellId = cells[_i7];
248
+ var pointsIDs = model.dataset.getCellPoints(cellId).cellPointIds;
249
+ var cellPts = [];
250
+ pointsIDs.forEach(function (id) {
251
+ var pt = [];
252
+ model.dataset.getPoints().getPoint(pointsIDs[id], pt);
253
+ cellPts.push(pt);
254
+ });
255
+ var c = [0, 0, 0];
256
+ var numPts = cellPts.length;
257
+ var negative = 0;
258
+ var positive = 0;
259
+
260
+ for (var j = 0; j < numPts; j++) {
261
+ var ptId = pointsIDs[j];
262
+ var x = model.dataset.getPoints().getPoint(ptId);
263
+ var val = n[0] * (x[0] - p[0]) + n[1] * (x[1] - p[1]) + n[2] * (x[2] - p[2]);
264
+ c[0] += x[0];
265
+ c[1] += x[1];
266
+ c[2] += x[2];
267
+
268
+ if (val < 0.0) {
269
+ negative = 1;
270
+ } else {
271
+ positive = 1;
272
+ }
273
+ }
274
+
275
+ if (negative && positive) {
276
+ // Use centroid to decide straddle cases
277
+ c[0] /= numPts;
278
+ c[1] /= numPts;
279
+ c[2] /= numPts;
280
+
281
+ var _val = n[0] * (c[0] - p[0]) + n[1] * (c[1] - p[1]) + n[2] * (c[2] - p[2]);
282
+
283
+ if (_val < 0.0) {
284
+ LHlist.push(cellId);
285
+ } else {
286
+ RHlist.push(cellId);
287
+ }
288
+ } else if (negative) {
289
+ LHlist.push(cellId);
290
+ } else {
291
+ RHlist.push(cellId);
292
+ }
293
+ };
294
+
295
+ for (var _i7 = 0; _i7 < numCells; _i7++) {
296
+ _loop(_i7);
297
+ } // for all cells
298
+ // evaluate this split
299
+
300
+
301
+ var numInLHnode = LHlist.length;
302
+ var numInRHnode = RHlist.length;
303
+ var ratio = Math.abs((numInRHnode - numInLHnode) / numCells); // see whether we've found acceptable split plane
304
+
305
+ if (ratio < 0.6 || foundBestSplit) {
306
+ // accept right off the bat
307
+ splitAcceptable = 1;
308
+ } else {
309
+ // not a great split try another
310
+ LHlist = [];
311
+ RHlist = [];
312
+
313
+ if (ratio < bestRatio) {
314
+ bestRatio = ratio;
315
+ bestPlane = splitPlane;
316
+ }
317
+
318
+ if (++splitPlane === 3 && bestRatio < 0.95) {
319
+ // at closing time, even the ugly ones look good
320
+ splitPlane = bestPlane;
321
+ foundBestSplit = 1;
322
+ }
323
+ } // try another split
324
+
325
+ } // for each split
326
+
327
+
328
+ if (splitAcceptable) {
329
+ // otherwise recursion terminates
330
+ var LHnode = vtkOBBNode.newInstance();
331
+ var RHnode = vtkOBBNode.newInstance();
332
+ obbNode.setKids([LHnode, RHnode]);
333
+ LHnode.setParent(obbNode);
334
+ RHnode.setParent(obbNode);
335
+ cells.length = 0;
336
+ buildTree(LHlist, LHnode, level + 1);
337
+ buildTree(RHlist, RHnode, level + 1);
338
+ } else {
339
+ // free up local objects
340
+ LHlist = [];
341
+ RHlist = [];
342
+ }
343
+ } // if should build tree
344
+
345
+
346
+ if (cells && model.retainCellLists) {
347
+ obbNode.setCells(cells);
348
+ } else if (cells) {
349
+ cells.length = 0;
350
+ }
351
+ }
352
+
353
+ function generatePolygons(obbNode, level, repLevel, points, cells) {
354
+ if (level === repLevel || repLevel < 0 && obbNode.getKids()) {
355
+ var nbPoints = points.getNumberOfPoints();
356
+ var newPoints = [];
357
+ var newCells = [];
358
+ var cubeIds = [];
359
+ newPoints.push.apply(newPoints, _toConsumableArray(obbNode.getCorner()));
360
+ cubeIds[0] = nbPoints++;
361
+ var x = [];
362
+ newPoints.push.apply(newPoints, _toConsumableArray(add(obbNode.getCorner(), obbNode.getAxis(0), x)));
363
+ cubeIds[1] = nbPoints++;
364
+ var y = [];
365
+ newPoints.push.apply(newPoints, _toConsumableArray(add(obbNode.getCorner(), obbNode.getAxis(1), y)));
366
+ cubeIds[2] = nbPoints++;
367
+ var xy = [];
368
+ newPoints.push.apply(newPoints, _toConsumableArray(add(x, obbNode.getAxis(1), xy)));
369
+ cubeIds[3] = nbPoints++;
370
+ var z = [];
371
+ newPoints.push.apply(newPoints, _toConsumableArray(add(obbNode.getCorner(), obbNode.getAxis(2), z)));
372
+ cubeIds[4] = nbPoints++;
373
+ var xz = [];
374
+ newPoints.push.apply(newPoints, _toConsumableArray(add(x, obbNode.getAxis(2), xz)));
375
+ cubeIds[5] = nbPoints++;
376
+ var yz = [];
377
+ newPoints.push.apply(newPoints, _toConsumableArray(add(y, obbNode.getAxis(2), yz)));
378
+ cubeIds[6] = nbPoints++;
379
+ var xyz = [];
380
+ newPoints.push.apply(newPoints, _toConsumableArray(add(xy, obbNode.getAxis(2), xyz)));
381
+ cubeIds[7] = nbPoints++;
382
+ newCells.push(4, cubeIds[0], cubeIds[2], cubeIds[3], cubeIds[1]);
383
+ newCells.push(4, cubeIds[0], cubeIds[1], cubeIds[5], cubeIds[4]);
384
+ newCells.push(4, cubeIds[0], cubeIds[4], cubeIds[6], cubeIds[2]);
385
+ newCells.push(4, cubeIds[1], cubeIds[3], cubeIds[7], cubeIds[5]);
386
+ newCells.push(4, cubeIds[4], cubeIds[5], cubeIds[7], cubeIds[6]);
387
+ newCells.push(4, cubeIds[2], cubeIds[6], cubeIds[7], cubeIds[3]);
388
+ points.setData(pushArray(points.getData(), newPoints));
389
+ cells.setData(pushArray(cells.getData(), newCells));
390
+ } else if ((level < repLevel || repLevel < 0) && obbNode.getKids()) {
391
+ generatePolygons(obbNode.getKids()[0], level + 1, repLevel, points, cells);
392
+ generatePolygons(obbNode.getKids()[1], level + 1, repLevel, points, cells);
393
+ }
394
+ }
395
+ /**
396
+ * Transform the whole OBB tree by using input transform
397
+ * @param {Transform} transform vtkjs Transform object
398
+ */
399
+
400
+
401
+ publicAPI.transform = function (transform) {
402
+ // Setup matrix used to transform vectors
403
+ var matrix = mat4.create();
404
+ mat4.copy(matrix, transform.getMatrix());
405
+ matrix[12] = 0;
406
+ matrix[13] = 0;
407
+ matrix[14] = 0;
408
+ matrix[15] = 1;
409
+ var transformVector = vtkMatrixBuilder.buildFromRadian().setMatrix(matrix);
410
+ var obbStack = new Array(model.level + 1);
411
+ obbStack[0] = model.tree;
412
+ var depth = 1;
413
+
414
+ while (depth > 0) {
415
+ depth -= 1;
416
+ var node = obbStack[depth];
417
+ var corner = node.getCorner();
418
+ var max = node.getAxis(0);
419
+ var mid = node.getAxis(1);
420
+ var min = node.getAxis(2);
421
+ transform.apply(corner);
422
+ transformVector.apply(max);
423
+ transformVector.apply(mid);
424
+ transformVector.apply(min);
425
+ node.setCorner(corner);
426
+ node.setAxes([max, mid, min]);
427
+
428
+ if (node.getKids() !== null) {
429
+ // push kids onto stack
430
+ obbStack[depth] = node.getKids()[0];
431
+ obbStack[depth + 1] = node.getKids()[1];
432
+ depth += 2;
433
+ }
434
+ }
435
+ };
436
+ /**
437
+ * Deep copy input node into class attribute tree
438
+ * @param {vtkOBBNode} tree
439
+ * @returns
440
+ */
441
+
442
+
443
+ publicAPI.deepCopy = function (tree) {
444
+ if (!tree) {
445
+ return;
446
+ }
447
+
448
+ publicAPI.setLevel(tree.getLevel());
449
+ publicAPI.setRetainCellLists(tree.getRetainCellLists());
450
+ publicAPI.setDataset(tree.getDataset());
451
+ publicAPI.setAutomatic(tree.getAutomatic());
452
+ publicAPI.setNumberOfCellsPerNode(tree.getNumberOfCellsPerNode());
453
+ publicAPI.setTolerance(tree.getTolerance());
454
+ var root = tree.getTree();
455
+
456
+ if (root) {
457
+ model.tree = vtkOBBNode.newInstance();
458
+ model.tree.deepCopy(root);
459
+ }
460
+ };
461
+ /**
462
+ * A method to compute the OBB of a dataset without having to go through the
463
+ * Execute method; It does set
464
+ * @param {vtkPolyData} input
465
+ * @param {Array[3]} corner
466
+ * @param {Array[3]} max
467
+ * @param {Array[3]} mid
468
+ * @param {Array[3]} min
469
+ * @param {Array[3]} size
470
+ */
471
+
472
+
473
+ publicAPI.computeOBBFromDataset = function (input, corner, max, mid, min, size) {
474
+ if (!input) {
475
+ return;
476
+ }
477
+
478
+ var numPts = input.getPoints().getNumberOfPoints();
479
+ var numCells = input.getNumberOfCells();
480
+
481
+ if (numPts < 1 || numCells < 1) {
482
+ vtkErrorMacro("Can't compute OBB - no data available!");
483
+ return;
484
+ }
485
+
486
+ model.dataset = input;
487
+ model.OBBCount = 0;
488
+ model.insertedPoints = Array.from({
489
+ length: numPts
490
+ }, function (_) {
491
+ return 0;
492
+ });
493
+ model.pointsList = [];
494
+ var cellList = Array.from({
495
+ length: numCells
496
+ }, function (_, i) {
497
+ return i;
498
+ });
499
+ computeOBB(cellList, corner, max, mid, min, size);
500
+ };
501
+ /**
502
+ * Returns true if nodeB and nodeA are disjoint after optional
503
+ * transformation of nodeB with matrix XformBtoA
504
+ * @param {vtkOBBNode} nodeA
505
+ * @param {vtkOBBNode} nodeB
506
+ * @param {mat4} XformBtoA
507
+ */
508
+
509
+
510
+ publicAPI.disjointOBBNodes = function (nodeA, nodeB, XformBtoA) {
511
+ if (!nodeA || !nodeB) {
512
+ return 5; // A and B are disjoint
513
+ }
514
+
515
+ var input = new Array(4);
516
+ var output = new Array(4);
517
+ var eps = model.tolerance;
518
+ var pA = nodeA;
519
+ var pB = vtkOBBNode.newInstance();
520
+ var dotAB = [[0, 0, 0], [0, 0, 0], [0, 0, 0]];
521
+
522
+ if (XformBtoA) {
523
+ // Here we assume that XformBtoA is an orthogonal matrix
524
+ input[0] = nodeB.getCorner()[0];
525
+ input[1] = nodeB.getCorner()[1];
526
+ input[2] = nodeB.getCorner()[2];
527
+ input[3] = 1.0;
528
+ vec4.transformMat4(output, input, XformBtoA);
529
+ pB.setCorner([output[0] / output[3], output[1] / output[3], output[2] / output[3]]); // Clean this up when the bug input MultiplyVectors is fixed!
530
+
531
+ for (var ii = 0; ii < 3; ii++) {
532
+ pB.getAxis(0)[ii] = nodeB.getCorner()[ii] + nodeB.getAxis(0)[ii];
533
+ pB.getAxis(1)[ii] = nodeB.getCorner()[ii] + nodeB.getAxis(1)[ii];
534
+ pB.getAxis(2)[ii] = nodeB.getCorner()[ii] + nodeB.getAxis(2)[ii];
535
+ }
536
+
537
+ for (var _ii = 0; _ii < 3; _ii++) {
538
+ input[0] = pB.getAxis(_ii)[0];
539
+ input[1] = pB.getAxis(_ii)[1];
540
+ input[2] = pB.getAxis(_ii)[2];
541
+ input[3] = 1.0;
542
+ vec4.transformMat4(output, input, XformBtoA);
543
+ pB.getAxis(_ii)[0] = output[0] / output[3];
544
+ pB.getAxis(_ii)[1] = output[1] / output[3];
545
+ pB.getAxis(_ii)[2] = output[2] / output[3];
546
+ }
547
+
548
+ for (var _ii2 = 0; _ii2 < 3; _ii2++) {
549
+ pB.getAxis(0)[_ii2] = pB.getAxis(0)[_ii2] - pB.getCorner()[_ii2];
550
+ pB.getAxis(1)[_ii2] = pB.getAxis(1)[_ii2] - pB.getCorner()[_ii2];
551
+ pB.getAxis(2)[_ii2] = pB.getAxis(2)[_ii2] - pB.getCorner()[_ii2];
552
+ }
553
+ } else {
554
+ pB = nodeB;
555
+ }
556
+
557
+ var centerA = [0, 0, 0];
558
+ var centerB = [0, 0, 0];
559
+ var AtoB = [0, 0, 0];
560
+
561
+ for (var _ii3 = 0; _ii3 < 3; _ii3++) {
562
+ centerA[_ii3] = pA.getCorner()[_ii3] + 0.5 * (pA.getAxis(0)[_ii3] + pA.getAxis(1)[_ii3] + pA.getAxis(2)[_ii3]);
563
+ centerB[_ii3] = pB.getCorner()[_ii3] + 0.5 * (pB.getAxis(0)[_ii3] + pB.getAxis(1)[_ii3] + pB.getAxis(2)[_ii3]);
564
+ AtoB[_ii3] = centerB[_ii3] - centerA[_ii3];
565
+ } // Project maximal and minimal corners onto line between centers
566
+
567
+
568
+ var rangeAmin = dot(pA.getCorner(), AtoB);
569
+ var rangeAmax = rangeAmin;
570
+ var rangeBmin = dot(pB.getCorner(), AtoB);
571
+ var rangeBmax = rangeBmin;
572
+ var dotA = 0;
573
+ var dotB = 0;
574
+
575
+ for (var _ii4 = 0; _ii4 < 3; _ii4++) {
576
+ // compute A range
577
+ dotA = dot(pA.getAxis(_ii4), AtoB);
578
+
579
+ if (dotA > 0) {
580
+ rangeAmax += dotA;
581
+ } else {
582
+ rangeAmin += dotA;
583
+ } // compute B range
584
+
585
+
586
+ dotB = dot(pB.getAxis(_ii4), AtoB);
587
+
588
+ if (dotB > 0) {
589
+ rangeBmax += dotB;
590
+ } else {
591
+ rangeBmin += dotB;
592
+ }
593
+ }
594
+
595
+ if (rangeAmax + eps < rangeBmin || rangeBmax + eps < rangeAmin) {
596
+ return 1; // A and B are Disjoint by the 1st test.
597
+ } // now check for a separation plane parallel to the faces of B
598
+
599
+
600
+ for (var _ii5 = 0; _ii5 < 3; _ii5++) {
601
+ // plane is normal to pB.getAxis(ii)
602
+ // computing B range is easy...
603
+ rangeBmin = dot(pB.getCorner(), pB.getAxis(_ii5));
604
+ rangeBmax = rangeBmin;
605
+ rangeBmax += dot(pB.getAxis(_ii5), pB.getAxis(_ii5)); // compute A range...
606
+
607
+ rangeAmin = dot(pA.getCorner(), pB.getAxis(_ii5));
608
+ rangeAmax = rangeAmin;
609
+
610
+ for (var jj = 0; jj < 3; jj++) {
611
+ // (note: we are saving all 9 dotproducts for future use)
612
+ dotA = dot(pB.getAxis(_ii5), pA.getAxis(jj));
613
+ dotAB[_ii5][jj] = dotA;
614
+
615
+ if (dotA > 0) {
616
+ rangeAmax += dotA;
617
+ } else {
618
+ rangeAmin += dotA;
619
+ }
620
+ }
621
+
622
+ if (rangeAmax + eps < rangeBmin || rangeBmax + eps < rangeAmin) {
623
+ return 2; // A and B are Disjoint by the 3rd test.
624
+ }
625
+ } // now check for a separation plane parallel to the faces of A
626
+
627
+
628
+ for (var _ii6 = 0; _ii6 < 3; _ii6++) {
629
+ // plane is normal to pA.getAxis(ii)
630
+ // computing A range is easy...
631
+ rangeAmin = dot(pA.getCorner(), pA.getAxis(_ii6));
632
+ rangeAmax = rangeAmin;
633
+ rangeAmax += dot(pA.getAxis(_ii6), pA.getAxis(_ii6)); // compute B range...
634
+
635
+ rangeBmin = dot(pB.getCorner(), pA.getAxis(_ii6));
636
+ rangeBmax = rangeBmin;
637
+
638
+ for (var _jj = 0; _jj < 3; _jj++) {
639
+ // (note: we are using the 9 dotproducts computed earlier)
640
+ dotB = dotAB[_jj][_ii6];
641
+
642
+ if (dotB > 0) {
643
+ rangeBmax += dotB;
644
+ } else {
645
+ rangeBmin += dotB;
646
+ }
647
+ }
648
+
649
+ if (rangeAmax + eps < rangeBmin || rangeBmax + eps < rangeAmin) {
650
+ return 3; // A and B are Disjoint by the 2nd test.
651
+ }
652
+ } // Bad luck: now we must look for a separation plane parallel
653
+ // to one edge from A and one edge from B.
654
+
655
+
656
+ for (var _ii7 = 0; _ii7 < 3; _ii7++) {
657
+ for (var _jj2 = 0; _jj2 < 3; _jj2++) {
658
+ // the plane is normal to pA.getAxis(ii) X pB.getAxis(jj)
659
+ cross(pA.getAxis(_ii7), pB.getAxis(_jj2), AtoB);
660
+ rangeAmin = dot(pA.getCorner(), AtoB);
661
+ rangeAmax = rangeAmin;
662
+ rangeBmin = dot(pB.getCorner(), AtoB);
663
+ rangeBmax = rangeBmin;
664
+
665
+ for (var kk = 0; kk < 3; kk++) {
666
+ // compute A range
667
+ dotA = dot(pA.getAxis(kk), AtoB);
668
+
669
+ if (dotA > 0) {
670
+ rangeAmax += dotA;
671
+ } else {
672
+ rangeAmin += dotA;
673
+ } // compute B range
674
+
675
+
676
+ dotB = dot(pB.getAxis(kk), AtoB);
677
+
678
+ if (dotB > 0) {
679
+ rangeBmax += dotB;
680
+ } else {
681
+ rangeBmin += dotB;
682
+ }
683
+ }
684
+
685
+ if (rangeAmax + eps < rangeBmin || rangeBmax + eps < rangeAmin) {
686
+ return 4; // A and B are Disjoint by the 4th test.
687
+ }
688
+ }
689
+ } // if we fall through to here, the OBB's overlap
690
+
691
+
692
+ return 0;
693
+ };
694
+ /**
695
+ * Intersect this OBBTree with OBBTreeB (as transformed) and
696
+ * call processing function for each intersecting leaf node pair.
697
+ * If the processing function returns a negative integer, terminate.
698
+ * For each intersecting leaf node pair, call callback.
699
+ * OBBTreeB is optionally transformed by XformBtoA before testing
700
+ * @param {vtkOBBTree} obbTreeB
701
+ * @param {mat4|null|undefined} XformBtoA
702
+ * @param {function|null|undefined} callback Compared function that takes in argument:
703
+ * nodeA (vtkOBBNode), nodeB (vtkOBBNode), XForm (mat4), arg
704
+ */
705
+
706
+
707
+ publicAPI.intersectWithOBBTree = function (obbTreeB, XformBtoA) {
708
+ var onIntersect = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function () {
709
+ return -1;
710
+ };
711
+ var maxDepth = model.level;
712
+ var minDepth = obbTreeB.getLevel();
713
+
714
+ if (minDepth > maxDepth) {
715
+ minDepth = maxDepth;
716
+ maxDepth = obbTreeB.getLevel();
717
+ }
718
+
719
+ var maxStackDepth = 3 * minDepth + 2 * (maxDepth - minDepth) + 1;
720
+ var OBBStackA = new Array(maxStackDepth);
721
+ var OBBStackB = new Array(maxStackDepth);
722
+ OBBStackA[0] = model.tree;
723
+ OBBStackB[0] = obbTreeB.getTree();
724
+ var depth = 1;
725
+ var count = 0;
726
+ var returnValue = 0; // simulate recursion without overhead of real recursion.
727
+
728
+ while (depth > 0 && returnValue > -1) {
729
+ depth--;
730
+ var nodeA = OBBStackA[depth];
731
+ var nodeB = OBBStackB[depth];
732
+
733
+ if (!publicAPI.disjointOBBNodes(nodeA, nodeB, XformBtoA)) {
734
+ // Collision
735
+ if (!nodeA.getKids()) {
736
+ if (!nodeB.getKids()) {
737
+ returnValue = onIntersect(nodeA, nodeB, XformBtoA);
738
+ count += Math.abs(returnValue);
739
+ } else {
740
+ // A is a leaf, but B goes deeper.
741
+ OBBStackA[depth] = nodeA;
742
+ OBBStackB[depth] = nodeB.getKids()[0];
743
+ OBBStackA[depth + 1] = nodeA;
744
+ OBBStackB[depth + 1] = nodeB.getKids()[1];
745
+ depth += 2;
746
+ }
747
+ } else if (!nodeB.getKids()) {
748
+ // B is a leaf, but A goes deeper.
749
+ OBBStackB[depth] = nodeB;
750
+ OBBStackA[depth] = nodeA.getKids()[0];
751
+ OBBStackB[depth + 1] = nodeB;
752
+ OBBStackA[depth + 1] = nodeA.getKids()[1];
753
+ depth += 2;
754
+ } else {
755
+ // neither A nor B are leaves. Go to the next level.
756
+ OBBStackA[depth] = nodeA.getKids()[0];
757
+ OBBStackB[depth] = nodeB.getKids()[0];
758
+ OBBStackA[depth + 1] = nodeA.getKids()[1];
759
+ OBBStackB[depth + 1] = nodeB.getKids()[0];
760
+ OBBStackA[depth + 2] = nodeA.getKids()[0];
761
+ OBBStackB[depth + 2] = nodeB.getKids()[1];
762
+ OBBStackA[depth + 3] = nodeA.getKids()[1];
763
+ OBBStackB[depth + 3] = nodeB.getKids()[1];
764
+ depth += 4;
765
+ }
766
+ }
767
+ }
768
+
769
+ return count;
770
+ };
771
+
772
+ publicAPI.triangleIntersectsNode = function (nodeA, p0, p1, p2, XformBtoA) {
773
+ var eps = model.tolerance;
774
+ var pA = nodeA;
775
+ var pB = [_toConsumableArray(p0), _toConsumableArray(p1), _toConsumableArray(p2)];
776
+
777
+ if (XformBtoA) {
778
+ // Here we assume that XformBtoA is an orthogonal matrix
779
+ var input = [0, 0, 0, 1];
780
+ var output = [];
781
+
782
+ for (var ii = 0; ii < 3; ii++) {
783
+ input[0] = pB[ii][0];
784
+ input[1] = pB[ii][1];
785
+ input[2] = pB[ii][2];
786
+ vec4.transformMat4(output, input, XformBtoA);
787
+ pB[ii][0] = output[0] / output[3];
788
+ pB[ii][1] = output[1] / output[3];
789
+ pB[ii][2] = output[2] / output[3];
790
+ }
791
+ } // now check for a separation plane parallel to the triangle
792
+
793
+
794
+ var v0 = [];
795
+ var v1 = [];
796
+
797
+ for (var _ii8 = 0; _ii8 < 3; _ii8++) {
798
+ // plane is normal to the triangle
799
+ v0[_ii8] = pB[1][_ii8] - pB[0][_ii8];
800
+ v1[_ii8] = pB[2][_ii8] - pB[0][_ii8];
801
+ }
802
+
803
+ var xprod = cross(v0, v1, []); // computing B range is easy...
804
+
805
+ var rangeBmax = dot(pB[0], xprod);
806
+ var rangeBmin = rangeBmax; // compute A range...
807
+
808
+ var rangeAmax = dot(pA.getCorner(), xprod);
809
+ var rangeAmin = rangeAmax;
810
+ var dotA;
811
+
812
+ for (var jj = 0; jj < 3; jj++) {
813
+ dotA = dot(xprod, pA.getAxis(jj));
814
+
815
+ if (dotA > 0) {
816
+ rangeAmax += dotA;
817
+ } else {
818
+ rangeAmin += dotA;
819
+ }
820
+ }
821
+
822
+ if (rangeAmax + eps < rangeBmin || rangeBmax + eps < rangeAmin) {
823
+ return 0; // A and B are Disjoint by the 1st test.
824
+ } // now check for a separation plane parallel to the faces of A
825
+
826
+
827
+ for (var _ii9 = 0; _ii9 < 3; _ii9++) {
828
+ // plane is normal to pA->Axes[ii]
829
+ // computing A range is easy...
830
+ rangeAmax = dot(pA.getCorner(), pA.getAxis(_ii9));
831
+ rangeAmin = rangeAmax;
832
+ rangeAmax += dot(pA.getAxis(_ii9), pA.getAxis(_ii9)); // compute B range...
833
+
834
+ rangeBmax = dot(pB[0], pA.getAxis(_ii9));
835
+ rangeBmin = rangeBmax;
836
+
837
+ var _dotB = dot(pB[1], pA.getAxis(_ii9));
838
+
839
+ if (_dotB > rangeBmax) {
840
+ rangeBmax = _dotB;
841
+ } else {
842
+ rangeBmin = _dotB;
843
+ }
844
+
845
+ _dotB = dot(pB[2], pA.getAxis(_ii9));
846
+
847
+ if (_dotB > rangeBmax) {
848
+ rangeBmax = _dotB;
849
+ } else if (_dotB < rangeBmin) {
850
+ rangeBmin = _dotB;
851
+ }
852
+
853
+ if (rangeAmax + eps < rangeBmin || rangeBmax + eps < rangeAmin) {
854
+ return 0; // A and B are Disjoint by the 2nd test.
855
+ }
856
+ } // Bad luck: now we must look for a separation plane parallel
857
+ // to one edge from A and one edge from B.
858
+
859
+
860
+ var AtoB = [];
861
+ var dotB;
862
+
863
+ for (var _ii10 = 0; _ii10 < 3; _ii10++) {
864
+ for (var _jj3 = 0; _jj3 < 3; _jj3++) {
865
+ // the plane is normal to pA->Axes[ii] X (pB[jj+1]-pB[jj])
866
+ v0[0] = pB[(_jj3 + 1) % 3][0] - pB[_jj3][0];
867
+ v0[1] = pB[(_jj3 + 1) % 3][1] - pB[_jj3][1];
868
+ v0[2] = pB[(_jj3 + 1) % 3][2] - pB[_jj3][2];
869
+ cross(pA.getAxis(_ii10), v0, AtoB);
870
+ rangeAmax = dot(pA.getCorner(), AtoB);
871
+ rangeAmin = rangeAmax;
872
+ rangeBmax = dot(pB[_jj3], AtoB);
873
+ rangeBmin = rangeBmax;
874
+
875
+ for (var kk = 0; kk < 3; kk++) {
876
+ // compute A range
877
+ dotA = dot(pA.getAxis(kk), AtoB);
878
+
879
+ if (dotA > 0) {
880
+ rangeAmax += dotA;
881
+ } else {
882
+ rangeAmin += dotA;
883
+ }
884
+ } // compute B range
885
+
886
+
887
+ dotB = dot(pB[(_jj3 + 2) % 3], AtoB);
888
+
889
+ if (dotB > rangeBmax) {
890
+ rangeBmax = dotB;
891
+ } else {
892
+ rangeBmin = dotB;
893
+ }
894
+
895
+ if (rangeAmax + eps < rangeBmin || rangeBmax + eps < rangeAmin) {
896
+ return 0; // A and B are Disjoint by the 3rd test.
897
+ }
898
+ }
899
+ } // if we fall through to here, the OBB overlaps the triangle.
900
+
901
+
902
+ return 1;
903
+ };
904
+ /**
905
+ *
906
+ * @param {*} info must be an object with { obbTree1, intersectionLines }
907
+ * @param {*} node0
908
+ * @param {*} node1
909
+ * @param {*} transform
910
+ * @returns the number of intersection lines found
911
+ */
912
+
913
+
914
+ publicAPI.findTriangleIntersections = function (info, node0, node1, transform) {
915
+ // Set up local structures to hold Impl array information
916
+ // vtkOBBTree* obbTree1 = info->OBBTree1;
917
+ // vtkCellArray* intersectionLines = info->IntersectionLines;
918
+ // vtkIdTypeArray* intersectionSurfaceId = info->SurfaceId;
919
+ // vtkIdTypeArray* intersectionCellIds0 = info->CellIds[0];
920
+ // vtkIdTypeArray* intersectionCellIds1 = info->CellIds[1];
921
+ // vtkPointLocator* pointMerger = info->PointMerger;
922
+ // double tolerance = info->Tolerance;
923
+ var mesh0 = publicAPI.getDataset();
924
+ var mesh1 = info.obbTree1.getDataset();
925
+ var pointOffset = info.intersectionLines.getPoints().getNumberOfPoints();
926
+ var intersectionPoints = [];
927
+ var intersectionLines = []; // The number of cells in OBBTree
928
+
929
+ var numCells0 = node0.getCells().length;
930
+
931
+ for (var id0 = 0; id0 < numCells0; id0++) {
932
+ var cellId0 = node0.getCells()[id0];
933
+ var type0 = mesh0.getCellType(cellId0); // Make sure the cell is a triangle
934
+
935
+ if (type0 === CellType.VTK_TRIANGLE) {
936
+ var _mesh0$getCellPoints = mesh0.getCellPoints(cellId0),
937
+ triPtIds0 = _mesh0$getCellPoints.cellPointIds;
938
+
939
+ var triPts0 = [[], [], []];
940
+
941
+ for (var id = 0; id < triPtIds0.length; id++) {
942
+ mesh0.getPoints().getPoint(triPtIds0[id], triPts0[id]);
943
+ }
944
+
945
+ if (info.obbTree1.triangleIntersectsNode(node1, triPts0[0], triPts0[1], triPts0[2], transform)) {
946
+ var numCells1 = node1.getCells().length;
947
+
948
+ for (var id1 = 0; id1 < numCells1; id1++) {
949
+ var cellId1 = node1.getCells()[id1];
950
+ var type1 = mesh1.getCellType(cellId1);
951
+
952
+ if (type1 === CellType.VTK_TRIANGLE) {
953
+ // See if the two cells actually intersect. If they do,
954
+ // add an entry into the intersection maps and add an
955
+ // intersection line.
956
+ var _mesh1$getCellPoints = mesh1.getCellPoints(cellId1),
957
+ triPtIds1 = _mesh1$getCellPoints.cellPointIds;
958
+
959
+ var triPts1 = [[], [], []];
960
+
961
+ for (var _id = 0; _id < triPtIds1.length; _id++) {
962
+ mesh1.getPoints().getPoint(triPtIds1[_id], triPts1[_id]);
963
+ }
964
+
965
+ var _vtkTriangle$intersec = vtkTriangle.intersectWithTriangle.apply(vtkTriangle, triPts0.concat(triPts1, [model.tolerance])),
966
+ intersect = _vtkTriangle$intersec.intersect,
967
+ coplanar = _vtkTriangle$intersec.coplanar,
968
+ outpt0 = _vtkTriangle$intersec.pt1,
969
+ outpt1 = _vtkTriangle$intersec.pt2;
970
+
971
+ if (intersect && !coplanar) {
972
+ var pointId = intersectionPoints.length / 3;
973
+ intersectionPoints.push.apply(intersectionPoints, _toConsumableArray(outpt0).concat(_toConsumableArray(outpt1)));
974
+ intersectionLines.push(2, pointOffset + pointId, pointOffset + pointId + 1);
975
+ } // If actual intersection, add point and cell to edge, line,
976
+ // and surface maps!
977
+
978
+ /*
979
+ if (coplanar) {
980
+ // Coplanar triangle intersection is not handled.
981
+ // This intersection will not be included in the output. TODO
982
+ // vtkDebugMacro(<<"Coplanar");
983
+ intersects = false;
984
+ continue;
985
+ }
986
+ if (intersects)
987
+ {
988
+ vtkIdType lineId = info.intersectionLines->GetNumberOfCells();
989
+ vtkIdType ptId0, ptId1;
990
+ int unique[2];
991
+ unique[0] = pointMerger->InsertUniquePoint(outpt0, ptId0);
992
+ unique[1] = pointMerger->InsertUniquePoint(outpt1, ptId1);
993
+ int addline = 1;
994
+ if (ptId0 == ptId1)
995
+ {
996
+ addline = 0;
997
+ }
998
+ if (ptId0 == ptId1 && surfaceid[0] != surfaceid[1])
999
+ {
1000
+ intersectionSurfaceId->InsertValue(ptId0, 3);
1001
+ }
1002
+ else
1003
+ {
1004
+ if (unique[0])
1005
+ {
1006
+ intersectionSurfaceId->InsertValue(ptId0, surfaceid[0]);
1007
+ }
1008
+ else
1009
+ {
1010
+ if (intersectionSurfaceId->GetValue(ptId0) != 3)
1011
+ {
1012
+ intersectionSurfaceId->InsertValue(ptId0, surfaceid[0]);
1013
+ }
1014
+ }
1015
+ if (unique[1])
1016
+ {
1017
+ intersectionSurfaceId->InsertValue(ptId1, surfaceid[1]);
1018
+ }
1019
+ else
1020
+ {
1021
+ if (intersectionSurfaceId->GetValue(ptId1) != 3)
1022
+ {
1023
+ intersectionSurfaceId->InsertValue(ptId1, surfaceid[1]);
1024
+ }
1025
+ }
1026
+ }
1027
+ info->IntersectionPtsMap[0]->insert(std::make_pair(ptId0, cellId0));
1028
+ info->IntersectionPtsMap[1]->insert(std::make_pair(ptId0, cellId1));
1029
+ info->IntersectionPtsMap[0]->insert(std::make_pair(ptId1, cellId0));
1030
+ info->IntersectionPtsMap[1]->insert(std::make_pair(ptId1, cellId1));
1031
+ // Check to see if duplicate line. Line can only be a duplicate
1032
+ // line if both points are not unique and they don't
1033
+ // equal each other
1034
+ if (!unique[0] && !unique[1] && ptId0 != ptId1)
1035
+ {
1036
+ vtkSmartPointer<vtkPolyData> lineTest = vtkSmartPointer<vtkPolyData>::New();
1037
+ lineTest->SetPoints(pointMerger->GetPoints());
1038
+ lineTest->SetLines(intersectionLines);
1039
+ lineTest->BuildLinks();
1040
+ int newLine = info->CheckLine(lineTest, ptId0, ptId1);
1041
+ if (newLine == 0)
1042
+ {
1043
+ addline = 0;
1044
+ }
1045
+ }
1046
+ if (addline)
1047
+ {
1048
+ // If the line is new and does not consist of two identical
1049
+ // points, add the line to the intersection and update
1050
+ // mapping information
1051
+ intersectionLines->InsertNextCell(2);
1052
+ intersectionLines->InsertCellPoint(ptId0);
1053
+ intersectionLines->InsertCellPoint(ptId1);
1054
+ intersectionCellIds0->InsertNextValue(cellId0);
1055
+ intersectionCellIds1->InsertNextValue(cellId1);
1056
+ info->PointCellIds[0]->InsertValue(ptId0, cellId0);
1057
+ info->PointCellIds[0]->InsertValue(ptId1, cellId0);
1058
+ info->PointCellIds[1]->InsertValue(ptId0, cellId1);
1059
+ info->PointCellIds[1]->InsertValue(ptId1, cellId1);
1060
+ info->IntersectionMap[0]->insert(std::make_pair(cellId0, lineId));
1061
+ info->IntersectionMap[1]->insert(std::make_pair(cellId1, lineId));
1062
+ // Check which edges of cellId0 and cellId1 outpt0 and
1063
+ // outpt1 are on, if any.
1064
+ int isOnEdge = 0;
1065
+ int m0p0 = 0, m0p1 = 0, m1p0 = 0, m1p1 = 0;
1066
+ for (vtkIdType edgeId = 0; edgeId < 3; edgeId++)
1067
+ {
1068
+ isOnEdge = info->AddToPointEdgeMap(
1069
+ 0, ptId0, outpt0, mesh0, cellId0, edgeId, lineId, triPtIds0);
1070
+ if (isOnEdge != -1)
1071
+ {
1072
+ m0p0++;
1073
+ }
1074
+ isOnEdge = info->AddToPointEdgeMap(
1075
+ 0, ptId1, outpt1, mesh0, cellId0, edgeId, lineId, triPtIds0);
1076
+ if (isOnEdge != -1)
1077
+ {
1078
+ m0p1++;
1079
+ }
1080
+ isOnEdge = info->AddToPointEdgeMap(
1081
+ 1, ptId0, outpt0, mesh1, cellId1, edgeId, lineId, triPtIds1);
1082
+ if (isOnEdge != -1)
1083
+ {
1084
+ m1p0++;
1085
+ }
1086
+ isOnEdge = info->AddToPointEdgeMap(
1087
+ 1, ptId1, outpt1, mesh1, cellId1, edgeId, lineId, triPtIds1);
1088
+ if (isOnEdge != -1)
1089
+ {
1090
+ m1p1++;
1091
+ }
1092
+ }
1093
+ // Special cases caught by tolerance and not from the Point
1094
+ // Merger
1095
+ if (m0p0 > 0 && m1p0 > 0)
1096
+ {
1097
+ intersectionSurfaceId->InsertValue(ptId0, 3);
1098
+ }
1099
+ if (m0p1 > 0 && m1p1 > 0)
1100
+ {
1101
+ intersectionSurfaceId->InsertValue(ptId1, 3);
1102
+ }
1103
+ }
1104
+ // Add information about origin surface to std::maps for
1105
+ // checks later
1106
+ if (intersectionSurfaceId->GetValue(ptId0) == 1)
1107
+ {
1108
+ info->IntersectionPtsMap[0]->insert(std::make_pair(ptId0, cellId0));
1109
+ }
1110
+ else if (intersectionSurfaceId->GetValue(ptId0) == 2)
1111
+ {
1112
+ info->IntersectionPtsMap[1]->insert(std::make_pair(ptId0, cellId1));
1113
+ }
1114
+ else
1115
+ {
1116
+ info->IntersectionPtsMap[0]->insert(std::make_pair(ptId0, cellId0));
1117
+ info->IntersectionPtsMap[1]->insert(std::make_pair(ptId0, cellId1));
1118
+ }
1119
+ if (intersectionSurfaceId->GetValue(ptId1) == 1)
1120
+ {
1121
+ info->IntersectionPtsMap[0]->insert(std::make_pair(ptId1, cellId0));
1122
+ }
1123
+ else if (intersectionSurfaceId->GetValue(ptId1) == 2)
1124
+ {
1125
+ info->IntersectionPtsMap[1]->insert(std::make_pair(ptId1, cellId1));
1126
+ }
1127
+ else
1128
+ {
1129
+ info->IntersectionPtsMap[0]->insert(std::make_pair(ptId1, cellId0));
1130
+ info->IntersectionPtsMap[1]->insert(std::make_pair(ptId1, cellId1));
1131
+ }
1132
+ }
1133
+ */
1134
+
1135
+ }
1136
+ }
1137
+ }
1138
+ }
1139
+ }
1140
+
1141
+ if (intersectionPoints.length) {
1142
+ var points = vtkPoints.newInstance();
1143
+ points.setData(pushArray(info.intersectionLines.getPoints().getData(), intersectionPoints));
1144
+ info.intersectionLines.setPoints(points);
1145
+ var lines = vtkCellArray.newInstance();
1146
+ lines.setData(pushArray(info.intersectionLines.getLines().getData(), intersectionLines));
1147
+ info.intersectionLines.setLines(lines);
1148
+ }
1149
+
1150
+ return intersectionLines.length / 3;
1151
+ };
1152
+ /**
1153
+ * Create polygonal representation for OBB tree at specified level. If
1154
+ * level < 0, then the leaf OBB nodes will be gathered. The aspect ratio (ar)
1155
+ * and line diameter (d) are used to control the building of the
1156
+ * representation. If a OBB node edge ratio's are greater than ar, then the
1157
+ * dimension of the OBB is collapsed (OBB->plane->line). A "line" OBB will be
1158
+ * represented either as two crossed polygons, or as a line, depending on
1159
+ * the relative diameter of the OBB compared to the diameter (d).
1160
+ * @param {Number} level Level of the representation
1161
+ * @returns {vtkPolyData}
1162
+ */
1163
+
1164
+
1165
+ publicAPI.generateRepresentation = function (level) {
1166
+ if (!model.tree) {
1167
+ vtkErrorMacro('No tree to generate representation for');
1168
+ return null;
1169
+ }
1170
+
1171
+ var points = vtkPoints.newInstance();
1172
+ var polys = vtkCellArray.newInstance();
1173
+ generatePolygons(model.tree, 0, level, points, polys);
1174
+ var output = vtkPolyData.newInstance();
1175
+ output.setPoints(points);
1176
+ output.setPolys(polys);
1177
+ return output;
1178
+ };
1179
+
1180
+ publicAPI.buildLocator = function () {
1181
+ if (model.dataset === null) {
1182
+ vtkErrorMacro("Can't build OBB tree - no data available!");
1183
+ return;
1184
+ }
1185
+
1186
+ var numPts = model.dataset.getPoints().getNumberOfPoints();
1187
+ var numCells = model.dataset.getNumberOfCells();
1188
+
1189
+ if (numPts < 1 || numCells < 1) {
1190
+ vtkErrorMacro("Can't build OBB tree - no data available!");
1191
+ return;
1192
+ }
1193
+
1194
+ model.OBBCount = 0; // Initialize an array of numPts elements set to value 0
1195
+
1196
+ model.insertedPoints = Array.from({
1197
+ length: numPts
1198
+ }, function (_) {
1199
+ return 0;
1200
+ });
1201
+ model.pointsList = [];
1202
+ var cellList = Array.from({
1203
+ length: numCells
1204
+ }, function (_, i) {
1205
+ return i;
1206
+ });
1207
+ model.tree = vtkOBBNode.newInstance();
1208
+ model.level = 0;
1209
+ buildTree(cellList, model.tree, 0);
1210
+ model.insertedPoints = [];
1211
+ model.pointsList = [];
1212
+ publicAPI.modified();
1213
+ };
1214
+ } // ----------------------------------------------------------------------------
1215
+
1216
+
1217
+ var DEFAULT_VALUES = {
1218
+ tolerance: 0.01,
1219
+ automatic: true,
1220
+ numberOfCellsPerNode: 32,
1221
+ dataset: null,
1222
+ tree: null,
1223
+ pointsList: [],
1224
+ insertedPoints: [],
1225
+ OBBCount: 0,
1226
+ level: 8,
1227
+ maxLevel: 8,
1228
+ retainCellLists: 1
1229
+ }; // ----------------------------------------------------------------------------
1230
+
1231
+ function extend(publicAPI, model) {
1232
+ var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
1233
+ Object.assign(model, DEFAULT_VALUES, initialValues); // Build VTK API
1234
+
1235
+ macro.setGet(publicAPI, model, ['tolerance', 'automatic', 'numberOfCellsPerNode', 'dataset', 'tree', 'maxLevel', 'level', 'retainCellLists']); // Make this a VTK object
1236
+
1237
+ macro.obj(publicAPI, model); // Object specific methods
1238
+
1239
+ vtkOBBTree(publicAPI, model);
1240
+ } // ----------------------------------------------------------------------------
1241
+
1242
+ var newInstance = macro.newInstance(extend, 'vtkOBBTree'); // ----------------------------------------------------------------------------
1243
+
1244
+ var vtkOBBTree$1 = {
1245
+ newInstance: newInstance,
1246
+ extend: extend
1247
+ };
1248
+
1249
+ export { vtkOBBTree$1 as default, extend, newInstance };