@kitware/vtk.js 25.5.0 → 25.7.1
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.
- package/Common/Core/CellArray.d.ts +20 -8
- package/Common/Core/CellArray.js +25 -6
- package/Common/Core/DataArray.d.ts +159 -15
- package/Common/Core/DataArray.js +181 -26
- package/Common/Core/Math/index.js +1 -1
- package/Common/Core/Math.js +1 -1
- package/Common/Core/Points.d.ts +6 -5
- package/Common/Core/Points.js +8 -4
- package/Common/DataModel/AbstractPointLocator.d.ts +54 -0
- package/Common/DataModel/AbstractPointLocator.js +40 -0
- package/Common/DataModel/DataSetAttributes/FieldData.d.ts +33 -22
- package/Common/DataModel/DataSetAttributes/FieldData.js +91 -9
- package/Common/DataModel/DataSetAttributes.d.ts +44 -0
- package/Common/DataModel/DataSetAttributes.js +11 -0
- package/Common/DataModel/IncrementalOctreeNode.d.ts +282 -0
- package/Common/DataModel/IncrementalOctreeNode.js +621 -0
- package/Common/DataModel/IncrementalOctreePointLocator.d.ts +61 -0
- package/Common/DataModel/IncrementalOctreePointLocator.js +342 -0
- package/Common/DataModel/Line.js +1 -1
- package/Common/DataModel/Locator.d.ts +43 -0
- package/Common/DataModel/Locator.js +37 -0
- package/Common/DataModel/Plane.js +1 -1
- package/Common/DataModel/Polygon/Constants.js +12 -0
- package/Common/DataModel/Polygon.d.ts +38 -4
- package/Common/DataModel/Polygon.js +210 -6
- package/Common/DataModel/Quad/Constants.js +9 -0
- package/Common/DataModel/Quad.d.ts +91 -0
- package/Common/DataModel/Quad.js +235 -0
- package/Common/DataModel/Triangle.d.ts +106 -81
- package/Common/DataModel/Triangle.js +1 -1
- package/Common/Transform/LandmarkTransform.js +1 -1
- package/Filters/Core/PolyDataNormals.js +1 -1
- package/Filters/General/ClipClosedSurface/Constants.js +10 -0
- package/Filters/General/ClipClosedSurface/ccsEdgeLocator.js +40 -0
- package/Filters/General/ClipClosedSurface.d.ts +95 -0
- package/Filters/General/ClipClosedSurface.js +971 -0
- package/Filters/General/ContourTriangulator/Constants.js +6 -0
- package/Filters/General/ContourTriangulator/helper.js +1951 -0
- package/Filters/General/ContourTriangulator.d.ts +122 -0
- package/Filters/General/ContourTriangulator.js +200 -0
- package/Filters/General/ImageMarchingCubes.js +1 -1
- package/Filters/General/MoleculeToRepresentation.js +1 -1
- package/Filters/General/OBBTree.js +1 -1
- package/Filters/General/TubeFilter.js +1 -1
- package/Filters/General/WindowedSincPolyDataFilter.js +1 -1
- package/Filters/Sources/PlaneSource.js +1 -1
- package/Filters/Texture/TextureMapToPlane.js +1 -1
- package/Interaction/Manipulators/KeyboardCameraManipulator.js +1 -1
- package/Interaction/Manipulators/MouseCameraAxisRotateManipulator.js +1 -1
- package/Interaction/Manipulators/MouseCameraTrackballPanManipulator.js +1 -1
- package/Interaction/Manipulators/MouseCameraTrackballRotateManipulator.js +1 -1
- package/Interaction/Manipulators/MouseCameraUnicamManipulator.js +1 -1
- package/Interaction/Manipulators/MouseCameraUnicamRotateManipulator.js +1 -1
- package/Interaction/Style/InteractorStyleMPRSlice.js +1 -1
- package/Proxy/Core/View2DProxy.js +1 -1
- package/Rendering/Core/Actor2D.d.ts +12 -6
- package/Rendering/Core/Camera.js +1 -1
- package/Rendering/Core/CellPicker.js +3 -2
- package/Rendering/Core/ColorTransferFunction/ColorMaps.d.ts +24 -0
- package/Rendering/Core/Light.js +1 -1
- package/Rendering/Core/Picker.js +1 -1
- package/Rendering/Core/Property2D.d.ts +1 -1
- package/Rendering/Core/VolumeProperty.d.ts +4 -4
- package/Rendering/Core/VolumeProperty.js +1 -1
- package/Rendering/OpenGL/PolyDataMapper.js +1 -1
- package/Rendering/WebGPU/BufferManager.js +1 -1
- package/Rendering/WebGPU/ForwardPass.js +93 -15
- package/Rendering/WebGPU/OpaquePass.js +1 -1
- package/Rendering/WebGPU/OrderIndependentTranslucentPass.js +1 -1
- package/Rendering/WebGPU/RenderEncoder.js +9 -5
- package/Rendering/WebGPU/RenderWindow.js +15 -13
- package/Rendering/WebGPU/TextureView.js +15 -2
- package/Rendering/WebGPU/VolumePass.js +1 -1
- package/Widgets/Core/StateBuilder/orientationMixin.js +1 -1
- package/Widgets/Manipulators/LineManipulator.js +1 -1
- package/Widgets/Manipulators/TrackballManipulator.js +1 -1
- package/Widgets/Representations/ResliceCursorContextRepresentation.js +1 -1
- package/Widgets/Widgets3D/LineWidget/behavior.js +1 -1
- package/Widgets/Widgets3D/LineWidget/helpers.js +1 -1
- package/Widgets/Widgets3D/ResliceCursorWidget/behavior.js +1 -1
- package/Widgets/Widgets3D/ResliceCursorWidget/helpers.js +1 -1
- package/Widgets/Widgets3D/ResliceCursorWidget.js +1 -1
- package/Widgets/Widgets3D/ShapeWidget/behavior.js +1 -1
- package/index.d.ts +8 -0
- package/package.json +1 -1
|
@@ -0,0 +1,621 @@
|
|
|
1
|
+
import macro from '../../macros.js';
|
|
2
|
+
import { f as distance2BetweenPoints } from '../Core/Math/index.js';
|
|
3
|
+
|
|
4
|
+
var vtkErrorMacro = macro.vtkErrorMacro;
|
|
5
|
+
var OCTREENODE_INSERTPOINT = [function (points, pointIdx, coords) {
|
|
6
|
+
return pointIdx;
|
|
7
|
+
}, function (points, pointIdx, coords) {
|
|
8
|
+
points.setTuple(pointIdx, coords);
|
|
9
|
+
return pointIdx;
|
|
10
|
+
}, function (points, pointIdx, coords) {
|
|
11
|
+
return points.insertNextTuple(coords);
|
|
12
|
+
}]; // Given the index (0 ~ 7) of a child node, the spatial bounding axis (0 ~ 2
|
|
13
|
+
// for x, y, and z), and the value (0 ~ 1 for min and max) to access, this LUT
|
|
14
|
+
// allows for rapid assignment of its spatial bounding box --- MinBounds[3]
|
|
15
|
+
// and MaxBounds[3], with each specific value or entry of this LUT pointing to
|
|
16
|
+
// MinBounds[3] for 0, center point for 1, or MaxBounds[3] for 2.
|
|
17
|
+
|
|
18
|
+
var OCTREE_CHILD_BOUNDS_LUT = [[[0, 1], [0, 1], [0, 1]], [[1, 2], [0, 1], [0, 1]], [[0, 1], [1, 2], [0, 1]], [[1, 2], [1, 2], [0, 1]], [[0, 1], [0, 1], [1, 2]], [[1, 2], [0, 1], [1, 2]], [[0, 1], [1, 2], [1, 2]], [[1, 2], [1, 2], [1, 2]]];
|
|
19
|
+
|
|
20
|
+
function vtkIncrementalOctreeNode(publicAPI, model) {
|
|
21
|
+
// Set our className
|
|
22
|
+
model.classHierarchy.push('vtkIncrementalOctreeNode'); //------------------------------------------------------------------------------
|
|
23
|
+
|
|
24
|
+
publicAPI.createPointIdSet = function (initSize, growSize) {
|
|
25
|
+
if (model.pointIdSet == null) {
|
|
26
|
+
model.pointIdSet = []; // TODO: use initSize and growSize.
|
|
27
|
+
// model.pointIdSet.allocate(initSize, growSize);
|
|
28
|
+
}
|
|
29
|
+
}; //------------------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
publicAPI.setBounds = function (x1, x2, y1, y2, z1, z2) {
|
|
33
|
+
if (model.minBounds == null) model.minBounds = [];
|
|
34
|
+
if (model.maxBounds == null) model.maxBounds = [];
|
|
35
|
+
if (model.minDataBounds == null) model.minDataBounds = [];
|
|
36
|
+
if (model.maxDataBounds == null) model.maxDataBounds = [];
|
|
37
|
+
model.minBounds[0] = x1;
|
|
38
|
+
model.maxBounds[0] = x2;
|
|
39
|
+
model.minBounds[1] = y1;
|
|
40
|
+
model.maxBounds[1] = y2;
|
|
41
|
+
model.minBounds[2] = z1;
|
|
42
|
+
model.maxBounds[2] = z2;
|
|
43
|
+
model.minDataBounds[0] = x2;
|
|
44
|
+
model.maxDataBounds[0] = x1;
|
|
45
|
+
model.minDataBounds[1] = y2;
|
|
46
|
+
model.maxDataBounds[1] = y1;
|
|
47
|
+
model.minDataBounds[2] = z2;
|
|
48
|
+
model.maxDataBounds[2] = z1;
|
|
49
|
+
}; //------------------------------------------------------------------------------
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
publicAPI.getBounds = function (bounds) {
|
|
53
|
+
bounds[0] = model.minBounds[0];
|
|
54
|
+
bounds[1] = model.maxBounds[0];
|
|
55
|
+
bounds[2] = model.minBounds[1];
|
|
56
|
+
bounds[3] = model.maxBounds[1];
|
|
57
|
+
bounds[4] = model.minBounds[2];
|
|
58
|
+
bounds[5] = model.maxBounds[2];
|
|
59
|
+
}; //------------------------------------------------------------------------------
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
publicAPI.updateCounterAndDataBounds = function (point, nHits, updateData) {
|
|
63
|
+
model.numberOfPoints += nHits;
|
|
64
|
+
if (!updateData) return false;
|
|
65
|
+
var updated = false;
|
|
66
|
+
|
|
67
|
+
if (point[0] < model.minDataBounds[0]) {
|
|
68
|
+
updated = true;
|
|
69
|
+
model.minDataBounds[0] = point[0];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (point[0] > model.maxDataBounds[0]) {
|
|
73
|
+
updated = true;
|
|
74
|
+
model.maxDataBounds[0] = point[0];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (point[1] < model.minDataBounds[1]) {
|
|
78
|
+
updated = true;
|
|
79
|
+
model.minDataBounds[1] = point[1];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (point[1] > model.maxDataBounds[1]) {
|
|
83
|
+
updated = true;
|
|
84
|
+
model.maxDataBounds[1] = point[1];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (point[2] < model.minDataBounds[2]) {
|
|
88
|
+
updated = true;
|
|
89
|
+
model.minDataBounds[2] = point[2];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (point[2] > model.maxDataBounds[2]) {
|
|
93
|
+
updated = true;
|
|
94
|
+
model.maxDataBounds[2] = point[2];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return updated;
|
|
98
|
+
}; //------------------------------------------------------------------------------
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
publicAPI.updateCounterAndDataBoundsRecursively = function (point, nHits, updateData, endNode) {
|
|
102
|
+
var updated = publicAPI.updateCounterAndDataBounds(point, nHits, updateData);
|
|
103
|
+
return model.parent === endNode ? updated : model.parent.updateCounterAndDataBoundsRecursively(point, nHits, updated, endNode);
|
|
104
|
+
}; //------------------------------------------------------------------------------
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
publicAPI.containsDuplicatePointsOnly = function (point) {
|
|
108
|
+
return model.minDataBounds[0] === point[0] && point[0] === model.maxDataBounds[0] && model.minDataBounds[1] === point[1] && point[1] === model.maxDataBounds[1] && model.minDataBounds[2] === point[2] && point[2] === model.maxDataBounds[2];
|
|
109
|
+
}; //------------------------------------------------------------------------------
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
publicAPI.isLeaf = function () {
|
|
113
|
+
return model.children == null;
|
|
114
|
+
}; //------------------------------------------------------------------------------
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
publicAPI.getChild = function (i) {
|
|
118
|
+
return model.children[i];
|
|
119
|
+
}; //------------------------------------------------------------------------------
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
publicAPI.separateExactlyDuplicatePointsFromNewInsertion = function (points, pntIds, newPnt, pntIdx, maxPts, ptMode) {
|
|
123
|
+
// the number of points already maintained in this leaf node
|
|
124
|
+
// >= maxPts AND all of them are exactly duplicate with one another
|
|
125
|
+
// BUT the new point is not a duplicate of them any more
|
|
126
|
+
var pointIdx = pntIdx;
|
|
127
|
+
var i;
|
|
128
|
+
var dupPnt = [0.0, 0.0, 0.0];
|
|
129
|
+
var octMin = [0.0, 0.0, 0.0];
|
|
130
|
+
var octMid = [0.0, 0.0, 0.0];
|
|
131
|
+
var octMax = [0.0, 0.0, 0.0];
|
|
132
|
+
var boxPtr = [null, null, null];
|
|
133
|
+
var ocNode = null;
|
|
134
|
+
var duplic = publicAPI;
|
|
135
|
+
var single = publicAPI; // the coordinate of the duplicate points: note pntIds == model.pointIdSet
|
|
136
|
+
|
|
137
|
+
points.getPoint(pntIds[0], dupPnt);
|
|
138
|
+
|
|
139
|
+
while (duplic === single) {
|
|
140
|
+
// as long as separation has not been achieved
|
|
141
|
+
// update the current (in recursion) node and access the bounding box info
|
|
142
|
+
ocNode = duplic;
|
|
143
|
+
octMid[0] = (ocNode.minBounds[0] + ocNode.maxBounds[0]) * 0.5;
|
|
144
|
+
octMid[1] = (ocNode.minBounds[1] + ocNode.maxBounds[1]) * 0.5;
|
|
145
|
+
octMid[2] = (ocNode.minBounds[2] + ocNode.maxBounds[2]) * 0.5;
|
|
146
|
+
boxPtr[0] = ocNode.minBounds;
|
|
147
|
+
boxPtr[1] = octMid;
|
|
148
|
+
boxPtr[2] = ocNode.maxBounds; // create eight child nodes
|
|
149
|
+
// FIXME: May be too slow to use vtk newInstance()
|
|
150
|
+
|
|
151
|
+
ocNode.children = [vtkIncrementalOctreeNode.newInstance(), vtkIncrementalOctreeNode.newInstance(), vtkIncrementalOctreeNode.newInstance(), vtkIncrementalOctreeNode.newInstance(), vtkIncrementalOctreeNode.newInstance(), vtkIncrementalOctreeNode.newInstance(), vtkIncrementalOctreeNode.newInstance(), vtkIncrementalOctreeNode.newInstance()];
|
|
152
|
+
|
|
153
|
+
for (i = 0; i < 8; i++) {
|
|
154
|
+
// x-bound: axis 0
|
|
155
|
+
octMin[0] = boxPtr[OCTREE_CHILD_BOUNDS_LUT[i][0][0]][0];
|
|
156
|
+
octMax[0] = boxPtr[OCTREE_CHILD_BOUNDS_LUT[i][0][1]][0]; // y-bound: axis 1
|
|
157
|
+
|
|
158
|
+
octMin[1] = boxPtr[OCTREE_CHILD_BOUNDS_LUT[i][1][0]][1];
|
|
159
|
+
octMax[1] = boxPtr[OCTREE_CHILD_BOUNDS_LUT[i][1][1]][1]; // z-bound: axis 2
|
|
160
|
+
|
|
161
|
+
octMin[2] = boxPtr[OCTREE_CHILD_BOUNDS_LUT[i][2][0]][2];
|
|
162
|
+
octMax[2] = boxPtr[OCTREE_CHILD_BOUNDS_LUT[i][2][1]][2];
|
|
163
|
+
ocNode.children[i] = vtkIncrementalOctreeNode.newInstance();
|
|
164
|
+
ocNode.children[i].setParent(ocNode);
|
|
165
|
+
ocNode.children[i].setBounds(octMin[0], octMax[0], octMin[1], octMax[1], octMin[2], octMax[2]);
|
|
166
|
+
} // determine the leaf node of the duplicate points & that of the new point
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
duplic = ocNode.children[ocNode.getChildIndex(dupPnt)];
|
|
170
|
+
single = ocNode.children[ocNode.getChildIndex(newPnt)];
|
|
171
|
+
} // Now the duplicate points have been separated from the new point //
|
|
172
|
+
// create a vtkIdList object for the new point
|
|
173
|
+
// update the counter and the data bounding box until the root node
|
|
174
|
+
// (including the root node)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
pointIdx = OCTREENODE_INSERTPOINT[ptMode](points, pointIdx, newPnt); // eslint-disable-next-line no-bitwise
|
|
178
|
+
|
|
179
|
+
single.createPointIdSet(maxPts >> 2, maxPts >> 1);
|
|
180
|
+
single.getPointIdSet().push(pointIdx);
|
|
181
|
+
single.updateCounterAndDataBoundsRecursively(newPnt, 1, 1, null); // We just need to reference pntIds while un-registering it from 'this'.
|
|
182
|
+
// This avoids deep-copying point ids from pntIds to duplic's PointIdSet.
|
|
183
|
+
// update the counter and the data bounding box, but until 'this' node
|
|
184
|
+
// (excluding 'this' node)
|
|
185
|
+
|
|
186
|
+
duplic.setPointIdSet(pntIds);
|
|
187
|
+
duplic.updateCounterAndDataBoundsRecursively(dupPnt, pntIds.length, 1, publicAPI);
|
|
188
|
+
return pointIdx;
|
|
189
|
+
}; //------------------------------------------------------------------------------
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
publicAPI.createChildNodes = function (points, pntIds, newPnt, pntIdx, maxPts, ptMode, numberOfNodes) {
|
|
193
|
+
// There are two scenarios for which this function is invoked.
|
|
194
|
+
//
|
|
195
|
+
// (1) the number of points already maintained in this leaf node
|
|
196
|
+
// == maxPts AND not all of them are exactly duplicate
|
|
197
|
+
// AND the new point is not a duplicate of them all
|
|
198
|
+
// (2) the number of points already maintained in this leaf node
|
|
199
|
+
// >= maxPts AND all of them are exactly duplicate with one another
|
|
200
|
+
// BUT the new point is not a duplicate of them any more
|
|
201
|
+
// address case (2) first if necessary
|
|
202
|
+
var nbNodes = numberOfNodes;
|
|
203
|
+
var pointIdx = pntIdx;
|
|
204
|
+
var sample = [];
|
|
205
|
+
points.getPoint(pntIds[0], sample);
|
|
206
|
+
|
|
207
|
+
if (publicAPI.containsDuplicatePointsOnly(sample)) {
|
|
208
|
+
pointIdx = publicAPI.separateExactlyDuplicatePointsFromNewInsertion(points, pntIds, newPnt, pointIdx, maxPts, ptMode);
|
|
209
|
+
return {
|
|
210
|
+
success: false,
|
|
211
|
+
nbNodes: nbNodes,
|
|
212
|
+
pointIdx: pointIdx
|
|
213
|
+
};
|
|
214
|
+
} // then address case (1) below
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
var i;
|
|
218
|
+
var target;
|
|
219
|
+
var dvidId = -1; // index of the sub-dividing octant, if any
|
|
220
|
+
|
|
221
|
+
var fullId = -1; // index of the full octant, if any
|
|
222
|
+
|
|
223
|
+
var numIds = [0, 0, 0, 0, 0, 0, 0, 0];
|
|
224
|
+
var octMin = [];
|
|
225
|
+
var octMax = [];
|
|
226
|
+
var tempPt = [];
|
|
227
|
+
var tempId;
|
|
228
|
+
var octMid = [(model.minBounds[0] + model.maxBounds[0]) * 0.5, (model.minBounds[1] + model.maxBounds[1]) * 0.5, (model.minBounds[2] + model.maxBounds[2]) * 0.5];
|
|
229
|
+
var boxPtr = [model.minBounds, octMid, model.maxBounds]; // create eight child nodes
|
|
230
|
+
|
|
231
|
+
model.children = [];
|
|
232
|
+
|
|
233
|
+
for (i = 0; i < 8; i++) {
|
|
234
|
+
// x-bound: axis 0
|
|
235
|
+
octMin[0] = boxPtr[OCTREE_CHILD_BOUNDS_LUT[i][0][0]][0];
|
|
236
|
+
octMax[0] = boxPtr[OCTREE_CHILD_BOUNDS_LUT[i][0][1]][0]; // y-bound: axis 1
|
|
237
|
+
|
|
238
|
+
octMin[1] = boxPtr[OCTREE_CHILD_BOUNDS_LUT[i][1][0]][1];
|
|
239
|
+
octMax[1] = boxPtr[OCTREE_CHILD_BOUNDS_LUT[i][1][1]][1]; // z-bound: axis 2
|
|
240
|
+
|
|
241
|
+
octMin[2] = boxPtr[OCTREE_CHILD_BOUNDS_LUT[i][2][0]][2];
|
|
242
|
+
octMax[2] = boxPtr[OCTREE_CHILD_BOUNDS_LUT[i][2][1]][2]; // This call internally sets the cener and default data bounding box, too.
|
|
243
|
+
|
|
244
|
+
model.children[i] = vtkIncrementalOctreeNode.newInstance();
|
|
245
|
+
model.children[i].iD = nbNodes++;
|
|
246
|
+
model.children[i].setParent(publicAPI);
|
|
247
|
+
model.children[i].setBounds(octMin[0], octMax[0], octMin[1], octMax[1], octMin[2], octMax[2]); // allocate a list of point-indices (size = 2^n) for index registration
|
|
248
|
+
// eslint-disable-next-line no-bitwise
|
|
249
|
+
|
|
250
|
+
model.children[i].createPointIdSet(maxPts >> 2, maxPts >> 1);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
boxPtr[0] = null;
|
|
254
|
+
boxPtr[1] = null;
|
|
255
|
+
boxPtr[2] = null; // distribute the available point-indices to the eight child nodes
|
|
256
|
+
|
|
257
|
+
for (i = 0; i < maxPts; i++) {
|
|
258
|
+
tempId = pntIds[i];
|
|
259
|
+
points.getPoint(tempId, tempPt);
|
|
260
|
+
target = publicAPI.getChildIndex(tempPt);
|
|
261
|
+
model.children[target].getPointIdSet().insertNextId(tempId);
|
|
262
|
+
model.children[target].updateCounterAndDataBounds(tempPt);
|
|
263
|
+
numIds[target]++;
|
|
264
|
+
} // locate the full child, just if any
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
for (i = 0; i < 8; i++) {
|
|
268
|
+
if (numIds[i] === maxPts) {
|
|
269
|
+
fullId = i;
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
target = publicAPI.getChildIndex(newPnt);
|
|
275
|
+
|
|
276
|
+
if (fullId === target) {
|
|
277
|
+
// The fact is that we are going to insert the new point to an already
|
|
278
|
+
// full octant (child node). Thus we need to further divide this child
|
|
279
|
+
// to avoid the overflow problem.
|
|
280
|
+
var _model$children$targe = model.children[target].createChildNodes(points, pntIds, newPnt, pointIdx, maxPts, ptMode, nbNodes);
|
|
281
|
+
|
|
282
|
+
nbNodes = _model$children$targe.numberOfNodes;
|
|
283
|
+
pointIdx = _model$children$targe.pointIdx;
|
|
284
|
+
dvidId = fullId;
|
|
285
|
+
} else {
|
|
286
|
+
// the initial division is a success
|
|
287
|
+
pointIdx = OCTREENODE_INSERTPOINT[ptMode](points, pointIdx, newPnt);
|
|
288
|
+
model.children[target].getPointIdSet().push(pointIdx);
|
|
289
|
+
model.children[target].updateCounterAndDataBoundsRecursively(newPnt, 1, 1, null); // NOTE: The counter below might reach the threshold, though we delay the
|
|
290
|
+
// sub-division of this child node until the next point insertion occurs.
|
|
291
|
+
|
|
292
|
+
numIds[target]++;
|
|
293
|
+
} // Now it is time to reclaim those un-used vtkIdList objects, of which each
|
|
294
|
+
// either is empty or still needs to be deleted due to further division of
|
|
295
|
+
// the child node. This post-deallocation of the un-used vtkIdList objects
|
|
296
|
+
// (of some child nodes) is based on the assumption that retrieving the
|
|
297
|
+
// 'maxPts' points from vtkPoints and the associated 'maxPts' point-indices
|
|
298
|
+
// from vtkIdList is more expensive than reclaiming at most 8 vtkIdList
|
|
299
|
+
// objects at hand.
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
for (i = 0; i < 8; i++) {
|
|
303
|
+
if (numIds[i] === 0 || i === dvidId) {
|
|
304
|
+
model.children[i].deletePointIdSet();
|
|
305
|
+
}
|
|
306
|
+
} // notify vtkIncrementalOctreeNode::InsertPoint() to destroy pntIds
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
return {
|
|
310
|
+
success: true,
|
|
311
|
+
numberOfNodes: nbNodes,
|
|
312
|
+
pointIdx: pointIdx
|
|
313
|
+
};
|
|
314
|
+
}; //------------------------------------------------------------------------------
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
publicAPI.insertPoint = function (points, newPnt, maxPts, pntId, ptMode, numberOfNodes) {
|
|
318
|
+
var nbNodes = 0;
|
|
319
|
+
var pointIdx = pntId;
|
|
320
|
+
|
|
321
|
+
if (model.pointIdSet) {
|
|
322
|
+
// there has been at least one point index
|
|
323
|
+
if (model.pointIdSet.length < maxPts || publicAPI.containsDuplicatePointsOnly(newPnt)) {
|
|
324
|
+
// this leaf node is not full or
|
|
325
|
+
// this leaf node is full, but of all exactly duplicate points
|
|
326
|
+
// and the point under check is another duplicate of these points
|
|
327
|
+
pointIdx = OCTREENODE_INSERTPOINT[ptMode](points, pointIdx, newPnt);
|
|
328
|
+
model.pointIdSet.push(pointIdx);
|
|
329
|
+
publicAPI.updateCounterAndDataBoundsRecursively(newPnt, 1, 1, null);
|
|
330
|
+
} else {
|
|
331
|
+
// overflow: divide this node and delete the list of point-indices.
|
|
332
|
+
// Note that the number of exactly duplicate points might be greater
|
|
333
|
+
// than or equal to maxPts.
|
|
334
|
+
var _publicAPI$createChil = publicAPI.createChildNodes(points, model.pointIdSet, newPnt, pointIdx, maxPts, ptMode, numberOfNodes);
|
|
335
|
+
|
|
336
|
+
nbNodes = _publicAPI$createChil.numberOfNodes;
|
|
337
|
+
pointIdx = _publicAPI$createChil.pointIdx;
|
|
338
|
+
model.pointIdSet = null;
|
|
339
|
+
}
|
|
340
|
+
} else {
|
|
341
|
+
// There has been no any point index registered in this leaf node
|
|
342
|
+
pointIdx = OCTREENODE_INSERTPOINT[ptMode](points, pointIdx, newPnt);
|
|
343
|
+
model.pointIdSet = [];
|
|
344
|
+
model.pointIdSet.push(pointIdx);
|
|
345
|
+
publicAPI.updateCounterAndDataBoundsRecursively(newPnt, 1, 1, null);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return {
|
|
349
|
+
numberOfNodes: numberOfNodes + nbNodes,
|
|
350
|
+
pointIdx: pointIdx
|
|
351
|
+
};
|
|
352
|
+
}; //------------------------------------------------------------------------------
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
publicAPI.getDistance2ToBoundary = function (point, closest, innerOnly, rootNode, checkData) {
|
|
356
|
+
// It is mandatory that GetMinDataBounds() and GetMaxDataBounds() be used.
|
|
357
|
+
// Direct access to MinDataBounds and MaxDataBounds might incur problems.
|
|
358
|
+
var thisMin = null;
|
|
359
|
+
var thisMax = null;
|
|
360
|
+
var rootMin = null;
|
|
361
|
+
var rootMax = null; // TODO: Check
|
|
362
|
+
// let minDist = VTK_DOUBLE_MAX;
|
|
363
|
+
|
|
364
|
+
var minDist = Number.MAX_VALUE; // minimum distance to the boundaries
|
|
365
|
+
|
|
366
|
+
if (checkData) {
|
|
367
|
+
thisMin = publicAPI.getMinDataBounds();
|
|
368
|
+
thisMax = publicAPI.getMaxDataBounds();
|
|
369
|
+
rootMin = rootNode.getMinDataBounds();
|
|
370
|
+
rootMax = rootNode.getMaxDataBounds();
|
|
371
|
+
} else {
|
|
372
|
+
thisMin = model.minBounds;
|
|
373
|
+
thisMax = model.maxBounds;
|
|
374
|
+
rootMin = rootNode.getMinBounds();
|
|
375
|
+
rootMax = rootNode.getMaxBounds();
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
var minFace = 0; // index of the face with min distance to the point
|
|
379
|
+
|
|
380
|
+
var beXless = Number(point[0] < thisMin[0]);
|
|
381
|
+
var beXmore = Number(point[0] > thisMax[0]);
|
|
382
|
+
var beYless = Number(point[1] < thisMin[1]);
|
|
383
|
+
var beYmore = Number(point[1] > thisMax[1]);
|
|
384
|
+
var beZless = Number(point[2] < thisMin[2]);
|
|
385
|
+
var beZmore = Number(point[2] > thisMax[2]);
|
|
386
|
+
var withinX = Number(!beXless && !beXmore);
|
|
387
|
+
var withinY = Number(!beYless && !beYmore);
|
|
388
|
+
var withinZ = Number(!beZless && !beZmore); // eslint-disable-next-line no-bitwise
|
|
389
|
+
|
|
390
|
+
var xyzFlag = (withinZ << 2) + (withinY << 1) + withinX;
|
|
391
|
+
|
|
392
|
+
switch (xyzFlag) {
|
|
393
|
+
case 0:
|
|
394
|
+
{
|
|
395
|
+
// withinZ = 0; withinY = 0; withinX = 0
|
|
396
|
+
// closest to a corner
|
|
397
|
+
closest[0] = beXless ? thisMin[0] : thisMax[0];
|
|
398
|
+
closest[1] = beYless ? thisMin[1] : thisMax[1];
|
|
399
|
+
closest[2] = beZless ? thisMin[2] : thisMax[2];
|
|
400
|
+
minDist = distance2BetweenPoints(point, closest);
|
|
401
|
+
break;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
case 1:
|
|
405
|
+
{
|
|
406
|
+
// withinZ = 0; withinY = 0; withinX = 1
|
|
407
|
+
// closest to an x-aligned edge
|
|
408
|
+
closest[0] = point[0];
|
|
409
|
+
closest[1] = beYless ? thisMin[1] : thisMax[1];
|
|
410
|
+
closest[2] = beZless ? thisMin[2] : thisMax[2];
|
|
411
|
+
minDist = distance2BetweenPoints(point, closest);
|
|
412
|
+
break;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
case 2:
|
|
416
|
+
{
|
|
417
|
+
// withinZ = 0; withinY = 1; withinX = 0
|
|
418
|
+
// closest to a y-aligned edge
|
|
419
|
+
closest[0] = beXless ? thisMin[0] : thisMax[0];
|
|
420
|
+
closest[1] = point[1];
|
|
421
|
+
closest[2] = beZless ? thisMin[2] : thisMax[2];
|
|
422
|
+
minDist = distance2BetweenPoints(point, closest);
|
|
423
|
+
break;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
case 3:
|
|
427
|
+
{
|
|
428
|
+
// withinZ = 0; withinY = 1; withinX = 1
|
|
429
|
+
// closest to a z-face
|
|
430
|
+
if (beZless) {
|
|
431
|
+
minDist = thisMin[2] - point[2];
|
|
432
|
+
closest[2] = thisMin[2];
|
|
433
|
+
} else {
|
|
434
|
+
minDist = point[2] - thisMax[2];
|
|
435
|
+
closest[2] = thisMax[2];
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
minDist *= minDist;
|
|
439
|
+
closest[0] = point[0];
|
|
440
|
+
closest[1] = point[1];
|
|
441
|
+
break;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
case 4:
|
|
445
|
+
{
|
|
446
|
+
// withinZ = 1; withinY = 0; withinX = 0
|
|
447
|
+
// cloest to a z-aligned edge
|
|
448
|
+
closest[0] = beXless ? thisMin[0] : thisMax[0];
|
|
449
|
+
closest[1] = beYless ? thisMin[1] : thisMax[1];
|
|
450
|
+
closest[2] = point[2];
|
|
451
|
+
minDist = distance2BetweenPoints(point, closest);
|
|
452
|
+
break;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
case 5:
|
|
456
|
+
{
|
|
457
|
+
// withinZ = 1; withinY = 0; withinX = 1
|
|
458
|
+
// closest to a y-face
|
|
459
|
+
if (beYless) {
|
|
460
|
+
minDist = thisMin[1] - point[1];
|
|
461
|
+
closest[1] = thisMin[1];
|
|
462
|
+
} else {
|
|
463
|
+
minDist = point[1] - thisMax[1];
|
|
464
|
+
closest[1] = thisMax[1];
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
minDist *= minDist;
|
|
468
|
+
closest[0] = point[0];
|
|
469
|
+
closest[2] = point[2];
|
|
470
|
+
break;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
case 6:
|
|
474
|
+
{
|
|
475
|
+
// withinZ = 1; withinY = 1; withinX = 0
|
|
476
|
+
// closest to an x-face
|
|
477
|
+
if (beXless) {
|
|
478
|
+
minDist = thisMin[0] - point[0];
|
|
479
|
+
closest[0] = thisMin[0];
|
|
480
|
+
} else {
|
|
481
|
+
minDist = point[0] - thisMax[0];
|
|
482
|
+
closest[0] = thisMax[0];
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
minDist *= minDist;
|
|
486
|
+
closest[1] = point[1];
|
|
487
|
+
closest[2] = point[2];
|
|
488
|
+
break;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
case 7:
|
|
492
|
+
{
|
|
493
|
+
// withinZ = 1; withinY = 1; withinZ = 1
|
|
494
|
+
// point is inside the box
|
|
495
|
+
if (innerOnly) {
|
|
496
|
+
// check only inner boundaries
|
|
497
|
+
var faceDst;
|
|
498
|
+
faceDst = point[0] - thisMin[0]; // x-min face
|
|
499
|
+
|
|
500
|
+
if (thisMin[0] !== rootMin[0] && faceDst < minDist) {
|
|
501
|
+
minFace = 0;
|
|
502
|
+
minDist = faceDst;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
faceDst = thisMax[0] - point[0]; // x-max face
|
|
506
|
+
|
|
507
|
+
if (thisMax[0] !== rootMax[0] && faceDst < minDist) {
|
|
508
|
+
minFace = 1;
|
|
509
|
+
minDist = faceDst;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
faceDst = point[1] - thisMin[1]; // y-min face
|
|
513
|
+
|
|
514
|
+
if (thisMin[1] !== rootMin[1] && faceDst < minDist) {
|
|
515
|
+
minFace = 2;
|
|
516
|
+
minDist = faceDst;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
faceDst = thisMax[1] - point[1]; // y-max face
|
|
520
|
+
|
|
521
|
+
if (thisMax[1] !== rootMax[1] && faceDst < minDist) {
|
|
522
|
+
minFace = 3;
|
|
523
|
+
minDist = faceDst;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
faceDst = point[2] - thisMin[2]; // z-min face
|
|
527
|
+
|
|
528
|
+
if (thisMin[2] !== rootMin[2] && faceDst < minDist) {
|
|
529
|
+
minFace = 4;
|
|
530
|
+
minDist = faceDst;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
faceDst = thisMax[2] - point[2]; // z-max face
|
|
534
|
+
|
|
535
|
+
if (thisMax[2] !== rootMax[2] && faceDst < minDist) {
|
|
536
|
+
minFace = 5;
|
|
537
|
+
minDist = faceDst;
|
|
538
|
+
}
|
|
539
|
+
} else {
|
|
540
|
+
// check all boundaries
|
|
541
|
+
var tmpDist = [point[0] - thisMin[0], thisMax[0] - point[0], point[1] - thisMin[1], thisMax[1] - point[1], point[2] - thisMin[2], thisMax[2] - point[2]];
|
|
542
|
+
|
|
543
|
+
for (var i = 0; i < 6; i++) {
|
|
544
|
+
if (tmpDist[i] < minDist) {
|
|
545
|
+
minFace = i;
|
|
546
|
+
minDist = tmpDist[i];
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
} // no square operation if no any inner boundary
|
|
550
|
+
|
|
551
|
+
|
|
552
|
+
if (minDist !== Number.MAX_VALUE) {
|
|
553
|
+
minDist *= minDist;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
closest[0] = point[0];
|
|
557
|
+
closest[1] = point[1];
|
|
558
|
+
closest[2] = point[2]; // minFace: the quad with the min distance to the point
|
|
559
|
+
// 0: x-min face ===> xyzIndx = 0: x and minFace & 1 = 0: thisMin
|
|
560
|
+
// 1: x-max face ===> xyzIndx = 0: x and minFace & 1 = 1: thisMax
|
|
561
|
+
// 2: y-min face ===> xyzIndx = 1: y and minFace & 1 = 0: thisMin
|
|
562
|
+
// 3: y-max face ===> xyzIndx = 1: y and minFace & 1 = 1: thisMax
|
|
563
|
+
// 4: z-min face ===> xyzIndx = 2: z and minFace & 1 = 0: thisMin
|
|
564
|
+
// 5: z-max face ===> xyzIndx = 2: z and minFace & 1 = 1: thisMax
|
|
565
|
+
|
|
566
|
+
var pMinMax = [thisMin, thisMax]; // eslint-disable-next-line no-bitwise
|
|
567
|
+
|
|
568
|
+
var xyzIndx = minFace >> 1; // eslint-disable-next-line no-bitwise
|
|
569
|
+
|
|
570
|
+
closest[xyzIndx] = pMinMax[minFace & 1][xyzIndx];
|
|
571
|
+
break;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
default:
|
|
575
|
+
vtkErrorMacro('unexpected case in getDistance2ToBoundary');
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
return minDist;
|
|
579
|
+
}; //------------------------------------------------------------------------------
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
publicAPI.getDistance2ToInnerBoundary = function (point, rootNode) {
|
|
583
|
+
var dummy = [];
|
|
584
|
+
return publicAPI.getDistance2ToBoundary(point, dummy, 0, rootNode, 0);
|
|
585
|
+
};
|
|
586
|
+
} // ----------------------------------------------------------------------------
|
|
587
|
+
// Object factory
|
|
588
|
+
// ----------------------------------------------------------------------------
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
var DEFAULT_VALUES = {
|
|
592
|
+
pointIdSet: null,
|
|
593
|
+
minBounds: null,
|
|
594
|
+
maxBounds: null,
|
|
595
|
+
minDataBounds: null,
|
|
596
|
+
maxDataBounds: null,
|
|
597
|
+
parent: null,
|
|
598
|
+
children: null
|
|
599
|
+
}; // ----------------------------------------------------------------------------
|
|
600
|
+
|
|
601
|
+
function extend(publicAPI, model) {
|
|
602
|
+
var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
603
|
+
Object.assign(model, DEFAULT_VALUES, initialValues); // Make this a VTK object
|
|
604
|
+
|
|
605
|
+
macro.obj(publicAPI, model);
|
|
606
|
+
macro.setGetArray(publicAPI, model, ['minBounds', 'maxBounds', 'minDataBounds', 'maxDataBounds'], 6);
|
|
607
|
+
macro.get(publicAPI, model, ['pointIdSet']); // TODO: No get?
|
|
608
|
+
|
|
609
|
+
macro.set(publicAPI, model, ['parent']); // Object specific methods
|
|
610
|
+
|
|
611
|
+
vtkIncrementalOctreeNode(publicAPI, model);
|
|
612
|
+
} // ----------------------------------------------------------------------------
|
|
613
|
+
|
|
614
|
+
var newInstance = macro.newInstance(extend, 'vtkIncrementalOctreeNode'); // ----------------------------------------------------------------------------
|
|
615
|
+
|
|
616
|
+
var vtkIncrementalOctreeNode$1 = {
|
|
617
|
+
newInstance: newInstance,
|
|
618
|
+
extend: extend
|
|
619
|
+
};
|
|
620
|
+
|
|
621
|
+
export { vtkIncrementalOctreeNode$1 as default, extend, newInstance };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { vtkObject } from './../../interfaces';
|
|
2
|
+
import vtkPoints from './../Core/Points';
|
|
3
|
+
import vtkIncrementalOctreeNode from './IncrementalOctreeNode';
|
|
4
|
+
import { IAbstractPointLocatorInitialValues } from './AbstractPointLocator';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
export interface IIncrementalOctreePointLocatorInitialValues
|
|
10
|
+
extends IAbstractPointLocatorInitialValues {
|
|
11
|
+
fudgeFactor: number;
|
|
12
|
+
octreeMaxDimSize: number;
|
|
13
|
+
buildCubicOctree: boolean;
|
|
14
|
+
maxPointsPerLeaf: number;
|
|
15
|
+
insertTolerance2: number;
|
|
16
|
+
locatorPoints: vtkPoints;
|
|
17
|
+
octreeRootNode: vtkIncrementalOctreeNode;
|
|
18
|
+
numberOfNodes: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type vtkIncrementalOctreePointLocatorBase = vtkObject;
|
|
22
|
+
|
|
23
|
+
export interface vtkIncrementalOctreePointLocator
|
|
24
|
+
extends vtkIncrementalOctreePointLocatorBase {}
|
|
25
|
+
|
|
26
|
+
// ----------------------------------------------------------------------------
|
|
27
|
+
// Static API
|
|
28
|
+
// ----------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Method use to decorate a given object (publicAPI+model) with vtkIncrementalOctreePointLocator characteristics.
|
|
32
|
+
*
|
|
33
|
+
* @param publicAPI object on which methods will be bounds (public)
|
|
34
|
+
* @param model object on which data structure will be bounds (protected)
|
|
35
|
+
* @param {object} [initialValues] (default: {})
|
|
36
|
+
*/
|
|
37
|
+
export function extend(
|
|
38
|
+
publicAPI: object,
|
|
39
|
+
model: object,
|
|
40
|
+
initialValues?: IIncrementalOctreePointLocatorInitialValues
|
|
41
|
+
): void;
|
|
42
|
+
|
|
43
|
+
// ----------------------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Method use to create a new instance of vtkIncrementalOctreePointLocator
|
|
47
|
+
* @param {IIncrementalOctreePointLocatorInitialValues} [initialValues] for pre-setting some of its content
|
|
48
|
+
*/
|
|
49
|
+
export function newInstance(
|
|
50
|
+
initialValues?: IIncrementalOctreePointLocatorInitialValues
|
|
51
|
+
): vtkIncrementalOctreePointLocator;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* vtkIncrementalOctreePointLocator
|
|
55
|
+
*/
|
|
56
|
+
export declare const vtkIncrementalOctreePointLocator: {
|
|
57
|
+
newInstance: typeof newInstance;
|
|
58
|
+
extend: typeof extend;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export default vtkIncrementalOctreePointLocator;
|