@kitware/vtk.js 29.1.2 → 29.1.3

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.
@@ -202,7 +202,7 @@ export function getMaxPoint(bounds: Bounds): Vector3;
202
202
  export function getCorners(bounds: Bounds, corners: Vector3[]): Vector3[];
203
203
 
204
204
  /**
205
- * Computes the two corner poitns with min and max coords.
205
+ * Computes the two corner points with min and max coords.
206
206
  * @param {Bounds} bounds
207
207
  * @param {Vector3} point1
208
208
  * @param {Vector3} point2
@@ -502,7 +502,7 @@ declare class BoundingBox {
502
502
  getCorners(bounds: Bounds, corners: Vector3[]): Vector3[];
503
503
 
504
504
  /**
505
- * Computes the two corner poitns with min and max coords.
505
+ * Computes the two corner points with min and max coords.
506
506
  * @param {Bounds} bounds
507
507
  * @param {Vector3} point1
508
508
  * @param {Vector3} point2
@@ -210,7 +210,7 @@ function getCorners(bounds, corners) {
210
210
  return corners;
211
211
  }
212
212
 
213
- // Computes the two corners with minimal and miximal coordinates
213
+ // Computes the two corners with minimal and maximal coordinates
214
214
  function computeCornerPoints(bounds, point1, point2) {
215
215
  point1[0] = bounds[0];
216
216
  point1[1] = bounds[2];
@@ -318,7 +318,7 @@ function intersectBox(bounds, origin, dir, coord, tolerance) {
318
318
  }
319
319
  }
320
320
 
321
- // Check for valie intersection along line
321
+ // Check for value intersection along line
322
322
  if (maxT[whichPlane] > 1.0 || maxT[whichPlane] < 0.0) {
323
323
  return 0;
324
324
  }
@@ -6,6 +6,11 @@ export interface IBoxInitialValues {
6
6
  bbox?: Bounds;
7
7
  }
8
8
 
9
+ export interface IBoxIntersections {
10
+ t1, t2: number;
11
+ x1, x2: Vector3;
12
+ }
13
+
9
14
  export interface vtkBox extends vtkObject {
10
15
 
11
16
  /**
@@ -26,6 +31,16 @@ export interface vtkBox extends vtkObject {
26
31
  */
27
32
  evaluateFunction(x: Vector3): number;
28
33
 
34
+ /**
35
+ * Intersect box with line and return the parametric values and points of the two intercepts
36
+ * @param bounds
37
+ * @param p1
38
+ * @param p2
39
+ * returns @object IBoxIntersections {t1, t2, x1, x2} object containing the t1, t2 parametric values and
40
+ * x1, x2 coordinates of the line intercept points in the bounding box or undefined
41
+ */
42
+ intersectWithLine(p1: Vector3, p2: Vector3) : IBoxIntersections | undefined;
43
+
29
44
  /**
30
45
  *
31
46
  * @param {Number} x The x coordinate.
@@ -61,6 +76,12 @@ export function extend(publicAPI: object, model: object, initialValues?: IBoxIni
61
76
  */
62
77
  export function newInstance(initialValues?: IBoxInitialValues): vtkBox;
63
78
 
79
+ //------------------------------------------------------------------------------
80
+ // Bounding box intersection code from David Gobbi. Go through the
81
+ // bounding planes one at a time and compute the parametric coordinate
82
+ // of each intersection and return the parametric values and the calculated points
83
+ export function intersectWithLine(bounds, p1, p2): IBoxIntersections | undefined;
84
+
64
85
  /**
65
86
  * vtkBox provides methods for creating a 1D cubic spline object from given
66
87
  * parameters, and allows for the calculation of the spline value and derivative
@@ -68,6 +89,7 @@ export function newInstance(initialValues?: IBoxInitialValues): vtkBox;
68
89
  */
69
90
  export declare const vtkBox: {
70
91
  newInstance: typeof newInstance,
71
- extend: typeof extend
92
+ extend: typeof extend,
93
+ intersectWithLine: typeof intersectWithLine
72
94
  };
73
95
  export default vtkBox;
@@ -5,6 +5,88 @@ import vtkBoundingBox from './BoundingBox.js';
5
5
  // Global methods
6
6
  // ----------------------------------------------------------------------------
7
7
 
8
+ //------------------------------------------------------------------------------
9
+ // Bounding box intersection code from David Gobbi. Go through the
10
+ // bounding planes one at a time and compute the parametric coordinate
11
+ // of each intersection and return the parametric values and the calculated points
12
+ function intersectWithLine(bounds, p1, p2) {
13
+ let plane1 = -1;
14
+ let plane2 = -1;
15
+ let t1 = 0.0;
16
+ let t2 = 1.0;
17
+ for (let j = 0; j < 3; j++) {
18
+ for (let k = 0; k < 2; k++) {
19
+ // Compute distances of p1 and p2 from the plane along the plane normal
20
+ const i = 2 * j + k;
21
+ const d1 = (bounds[i] - p1[j]) * (1 - 2 * k);
22
+ const d2 = (bounds[i] - p2[j]) * (1 - 2 * k);
23
+
24
+ // If both distances are positive, both points are outside
25
+ if (d1 > 0 && d2 > 0) {
26
+ return;
27
+ }
28
+ // If one of the distances is positive, the line crosses the plane
29
+ if (d1 > 0 || d2 > 0) {
30
+ // Compute fractional distance "t" of the crossing between p1 & p2
31
+ let t = 0.0;
32
+ if (d1 !== 0) {
33
+ t = d1 / (d1 - d2);
34
+ }
35
+
36
+ // If point p1 was clipped, adjust t1
37
+ if (d1 > 0) {
38
+ if (t >= t1) {
39
+ t1 = t;
40
+ plane1 = i;
41
+ }
42
+ }
43
+ // else point p2 was clipped, so adjust t2
44
+ else if (t <= t2) {
45
+ t2 = t;
46
+ plane2 = i;
47
+ }
48
+ // If this happens, there's no line left
49
+ if (t1 > t2) {
50
+ // Allow for planes that are coincident or slightly inverted
51
+ if (plane1 < 0 || plane2 < 0) {
52
+ return;
53
+ }
54
+ }
55
+ }
56
+ }
57
+ }
58
+ function getValues(plane, t) {
59
+ const x = [0, 0, 0];
60
+ for (let count = 0; count < 2; count++) {
61
+ for (let i = 0; i < 3; i++) {
62
+ if (plane === 2 * i || plane === 2 * i + 1) {
63
+ x[i] = bounds[plane];
64
+ } else {
65
+ x[i] = p1[i] * (1.0 - t) + p2[i] * t;
66
+ if (x[i] < bounds[2 * i]) {
67
+ x[i] = bounds[2 * i];
68
+ }
69
+ if (x[i] > bounds[2 * i + 1]) {
70
+ x[i] = bounds[2 * i + 1];
71
+ }
72
+ }
73
+ }
74
+ }
75
+ return x;
76
+ }
77
+ const x1 = getValues(plane1, t1);
78
+ const x2 = getValues(plane2, t2);
79
+ const outObject = {
80
+ t1,
81
+ t2,
82
+ x1,
83
+ x2
84
+ };
85
+
86
+ // eslint-disable-next-line consistent-return
87
+ return outObject;
88
+ }
89
+
8
90
  // ----------------------------------------------------------------------------
9
91
  // Static API
10
92
  // ----------------------------------------------------------------------------
@@ -14,7 +96,6 @@ const STATIC = {};
14
96
  // ----------------------------------------------------------------------------
15
97
  // vtkBox methods
16
98
  // ----------------------------------------------------------------------------
17
-
18
99
  function vtkBox(publicAPI, model) {
19
100
  // Set our className
20
101
  model.classHierarchy.push('vtkBox');
@@ -67,7 +148,7 @@ function vtkBox(publicAPI, model) {
67
148
  dist = point[i] - maxPoint[i];
68
149
  }
69
150
  if (dist > minDistance) {
70
- // remember, it's engative
151
+ // remember, it's negative
71
152
  minDistance = dist;
72
153
  }
73
154
  } // end if inside
@@ -103,6 +184,7 @@ function vtkBox(publicAPI, model) {
103
184
  publicAPI.modified();
104
185
  };
105
186
  publicAPI.addBox = other => publicAPI.addBounds(other.getBounds());
187
+ publicAPI.intersectWithLine = (p1, p2) => intersectWithLine(model.bbox, p1, p2);
106
188
  }
107
189
 
108
190
  // ----------------------------------------------------------------------------
@@ -133,7 +215,8 @@ const newInstance = macro.newInstance(extend, 'vtkBox');
133
215
  var vtkBox$1 = {
134
216
  newInstance,
135
217
  extend,
218
+ intersectWithLine,
136
219
  ...STATIC
137
220
  };
138
221
 
139
- export { STATIC, vtkBox$1 as default, extend, newInstance };
222
+ export { STATIC, vtkBox$1 as default, extend, intersectWithLine, newInstance };
@@ -5,10 +5,11 @@ import vtkPicker from './Picker.js';
5
5
  import vtkPolyLine from '../../Common/DataModel/PolyLine.js';
6
6
  import vtkTriangle from '../../Common/DataModel/Triangle.js';
7
7
  import vtkQuad from '../../Common/DataModel/Quad.js';
8
- import { l as normalize, G as isIdentity3x3 } from '../../Common/Core/Math/index.js';
8
+ import { l as normalize, G as isIdentity3x3, e as distance2BetweenPoints } from '../../Common/Core/Math/index.js';
9
9
  import { CellType } from '../../Common/DataModel/CellTypes/Constants.js';
10
10
  import { vec3, vec4 } from 'gl-matrix';
11
11
  import vtkMatrixBuilder from '../../Common/Core/MatrixBuilder.js';
12
+ import vtkBox from '../../Common/DataModel/Box.js';
12
13
 
13
14
  // ----------------------------------------------------------------------------
14
15
  // Global methods
@@ -159,8 +160,8 @@ function vtkCellPicker(publicAPI, model) {
159
160
  };
160
161
  publicAPI.intersectWithLine = (p1, p2, tol, actor, mapper) => {
161
162
  let tMin = Number.MAX_VALUE;
162
- const t1 = 0.0;
163
- const t2 = 1.0;
163
+ let t1 = 0.0;
164
+ let t2 = 1.0;
164
165
  const vtkCellPickerPlaneTol = 1e-14;
165
166
  const clipLine = clipLineWithPlane(mapper, model.transformMatrix, p1, p2);
166
167
  if (mapper && !clipLine.intersect) {
@@ -174,7 +175,13 @@ function vtkCellPicker(publicAPI, model) {
174
175
  model.pCoords = pickData.pCoords;
175
176
  }
176
177
  } else if (mapper.isA('vtkVolumeMapper')) {
177
- tMin = publicAPI.intersectVolumeWithLine(p1, p2, clipLine.t1, clipLine.t2, tol, actor);
178
+ // we calculate here the parametric intercept points between the ray and the bounding box, so
179
+ // if the application defines for some reason a too large ray length (1e6), it restrict the calculation
180
+ // to the vtkVolume actor bounding box
181
+ const interceptionObject = vtkBox.intersectWithLine(mapper.getBounds(), p1, p2);
182
+ t1 = interceptionObject?.t1 > clipLine.t1 ? interceptionObject.t1 : clipLine.t1;
183
+ t2 = interceptionObject?.t2 < clipLine.t2 ? interceptionObject.t2 : clipLine.t2;
184
+ tMin = publicAPI.intersectVolumeWithLine(p1, p2, t1, t2, tol, actor);
178
185
  } else if (mapper.isA('vtkMapper')) {
179
186
  tMin = publicAPI.intersectActorWithLine(p1, p2, t1, t2, tol, mapper);
180
187
  }
@@ -255,16 +262,19 @@ function vtkCellPicker(publicAPI, model) {
255
262
  const x1 = [0, 0, 0];
256
263
  const x2 = [0, 0, 0];
257
264
  for (let i = 0; i < 3; i++) {
258
- x1[i] = (p1[i] - origin[i]) / spacing[i];
259
- x2[i] = (p2[i] - origin[i]) / spacing[i];
265
+ x1[i] = (q1[i] - origin[i]) / spacing[i];
266
+ x2[i] = (q2[i] - origin[i]) / spacing[i];
260
267
  }
261
268
  const x = [0, 0, 0, 0];
262
269
  const xi = [0, 0, 0];
263
270
  const sliceSize = dims[1] * dims[0];
264
271
  const rowSize = dims[0];
265
- const nSteps = 100;
272
+ // here the step is the 1 over the distance between volume index location x1 and x2
273
+ const step = 1 / Math.sqrt(distance2BetweenPoints(x1, x2));
266
274
  let insideVolume;
267
- for (let t = t1; t < t2; t += 1 / nSteps) {
275
+ // here we reinterpret the t value as the distance between x1 and x2
276
+ // When calculating the tMin, we weight t between t1 and t2 values
277
+ for (let t = 0; t < 1; t += step) {
268
278
  // calculate the location of the point
269
279
  insideVolume = true;
270
280
  for (let j = 0; j < 3; j++) {
@@ -297,7 +307,8 @@ function vtkCellPicker(publicAPI, model) {
297
307
  value = Math.floor((value - oRange[0]) * scale);
298
308
  const opacity = tmpTable[value];
299
309
  if (opacity > model.opacityThreshold) {
300
- tMin = t;
310
+ // returning the tMin to the original scale, if t1 > 0 or t2 < 1
311
+ tMin = t1 * (1.0 - t) + t2 * t;
301
312
  break;
302
313
  }
303
314
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitware/vtk.js",
3
- "version": "29.1.2",
3
+ "version": "29.1.3",
4
4
  "description": "Visualization Toolkit for the Web",
5
5
  "keywords": [
6
6
  "3d",