@kitware/vtk.js 30.5.2 → 30.6.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 (35) hide show
  1. package/Common/Core/Math/index.js +1 -1
  2. package/Common/Core/Math.js +1 -1
  3. package/Rendering/Core/CellPicker.js +12 -22
  4. package/Rendering/Core/ColorTransferFunction/CssFilters.js +1 -1
  5. package/Rendering/Core/ColorTransferFunction.js +1 -1
  6. package/Rendering/Core/Coordinate.js +1 -1
  7. package/Rendering/Core/CubeAxesActor.js +1 -1
  8. package/Rendering/Core/ImageMapper.js +1 -1
  9. package/Rendering/Core/Renderer.js +1 -1
  10. package/Rendering/Core/ScalarBarActor.js +1 -1
  11. package/Rendering/Core/VolumeMapper.js +1 -1
  12. package/Rendering/OpenGL/PolyDataMapper2D.js +1 -1
  13. package/Rendering/OpenGL/Texture.js +1 -1
  14. package/Widgets/Manipulators/AbstractManipulator.d.ts +28 -2
  15. package/Widgets/Manipulators/AbstractManipulator.js +20 -0
  16. package/Widgets/Manipulators/CPRManipulator.js +3 -3
  17. package/Widgets/Manipulators/LineManipulator.js +1 -1
  18. package/Widgets/Manipulators/PickerManipulator.js +2 -2
  19. package/Widgets/Manipulators/PlaneManipulator.js +1 -1
  20. package/Widgets/Manipulators/TrackballManipulator.js +2 -2
  21. package/Widgets/Widgets3D/AngleWidget/behavior.js +14 -7
  22. package/Widgets/Widgets3D/AngleWidget.js +1 -1
  23. package/Widgets/Widgets3D/ImageCroppingWidget/behavior.js +19 -6
  24. package/Widgets/Widgets3D/ImplicitPlaneWidget.js +18 -6
  25. package/Widgets/Widgets3D/LabelWidget/behavior.js +14 -10
  26. package/Widgets/Widgets3D/LineWidget/behavior.js +22 -12
  27. package/Widgets/Widgets3D/PolyLineWidget/behavior.js +16 -4
  28. package/Widgets/Widgets3D/PolyLineWidget.js +0 -5
  29. package/Widgets/Widgets3D/ResliceCursorWidget/behavior.js +1 -1
  30. package/Widgets/Widgets3D/ResliceCursorWidget/helpers.js +1 -1
  31. package/Widgets/Widgets3D/SeedWidget/behavior.js +1 -7
  32. package/Widgets/Widgets3D/ShapeWidget/behavior.js +9 -8
  33. package/Widgets/Widgets3D/SphereWidget/behavior.js +20 -29
  34. package/Widgets/Widgets3D/SplineWidget/behavior.js +16 -4
  35. package/package.json +1 -1
@@ -2245,4 +2245,4 @@ var vtkMath$1 = /*#__PURE__*/Object.freeze({
2245
2245
  'default': vtkMath
2246
2246
  });
2247
2247
 
2248
- export { max as $, degreesFromRadians as A, areEquals as B, clampValue as C, arrayRange as D, getMajorAxisIndex as E, createUninitializedBounds as F, isIdentity3x3 as G, identity as H, multiplyMatrix as I, floor as J, isInf as K, rgb2hsv as L, rgb2lab as M, lab2rgb as N, round as O, normalize2D as P, nearestPowerOfTwo as Q, multiply3x3_vect3 as R, getSparseOrthogonalMatrix as S, areBoundsInitialized as T, isPowerOfTwo as U, angleBetweenVectors as V, signedAngleBetweenVectors as W, createArray as X, Pi as Y, ceil as Z, min as _, areMatricesEqual as a, float2CssRGBA as a$, arrayMin as a0, arrayMax as a1, ceilLog2 as a2, factorial as a3, binomial as a4, beginCombination as a5, nextCombination as a6, randomSeed as a7, getSeed as a8, gaussian as a9, diagonalize3x3 as aA, singularValueDecomposition3x3 as aB, luFactorLinearSystem as aC, luSolveLinearSystem as aD, invertMatrix as aE, estimateMatrixCondition as aF, solveHomogeneousLeastSquares as aG, solveLeastSquares as aH, hex2float as aI, lab2xyz as aJ, xyz2lab as aK, xyz2rgb as aL, rgb2xyz as aM, computeBoundsFromPoints as aN, clampAndNormalizeValue as aO, getScalarTypeFittingRange as aP, getAdjustedScalarRange as aQ, extentIsWithinOtherExtent as aR, boundsIsWithinOtherBounds as aS, pointIsWithinBounds as aT, solve3PointCircle as aU, inf as aV, negInf as aW, isFinite as aX, isNaN as aY, floatToHex2 as aZ, floatRGB2HexCode as a_, multiplyScalar2D as aa, multiplyAccumulate2D as ab, outer as ac, projectVector as ad, dot2D as ae, projectVector2D as af, gaussianAmplitude as ag, gaussianWeight as ah, outer2D as ai, norm2D as aj, rowsToMat4 as ak, columnsToMat4 as al, columnsToMat3 as am, LUFactor3x3 as an, LUSolve3x3 as ao, linearSolve3x3 as ap, multiply3x3_mat3 as aq, transpose3x3 as ar, invert3x3 as as, identity3x3 as at, isIdentity as au, quaternionToMatrix3x3 as av, roundNumber as aw, matrix3x3ToQuaternion as ax, multiplyQuaternion as ay, orthogonalize3x3 as az, roundVector as b, clampVector as c, dot as d, distance2BetweenPoints as e, vtkMath as f, solveLinearSystem as g, hsv2rgb as h, isNan as i, cross as j, add as k, normalize as l, multiplyAccumulate as m, norm as n, determinant2x2 as o, jacobiN as p, perpendiculars as q, radiansFromDegrees as r, subtract as s, jacobi as t, uninitializeBounds as u, vtkMath$1 as v, multiplyScalar as w, random as x, determinant3x3 as y, rowsToMat3 as z };
2248
+ export { arrayMin as $, degreesFromRadians as A, areEquals as B, clampValue as C, arrayRange as D, getMajorAxisIndex as E, createUninitializedBounds as F, identity as G, multiplyMatrix as H, floor as I, isInf as J, rgb2hsv as K, rgb2lab as L, lab2rgb as M, round as N, normalize2D as O, nearestPowerOfTwo as P, multiply3x3_vect3 as Q, getSparseOrthogonalMatrix as R, areBoundsInitialized as S, isPowerOfTwo as T, angleBetweenVectors as U, signedAngleBetweenVectors as V, createArray as W, Pi as X, ceil as Y, min as Z, max as _, areMatricesEqual as a, float2CssRGBA as a$, arrayMax as a0, ceilLog2 as a1, factorial as a2, binomial as a3, beginCombination as a4, nextCombination as a5, randomSeed as a6, getSeed as a7, gaussian as a8, multiplyScalar2D as a9, diagonalize3x3 as aA, singularValueDecomposition3x3 as aB, luFactorLinearSystem as aC, luSolveLinearSystem as aD, invertMatrix as aE, estimateMatrixCondition as aF, solveHomogeneousLeastSquares as aG, solveLeastSquares as aH, hex2float as aI, lab2xyz as aJ, xyz2lab as aK, xyz2rgb as aL, rgb2xyz as aM, computeBoundsFromPoints as aN, clampAndNormalizeValue as aO, getScalarTypeFittingRange as aP, getAdjustedScalarRange as aQ, extentIsWithinOtherExtent as aR, boundsIsWithinOtherBounds as aS, pointIsWithinBounds as aT, solve3PointCircle as aU, inf as aV, negInf as aW, isFinite as aX, isNaN as aY, floatToHex2 as aZ, floatRGB2HexCode as a_, multiplyAccumulate2D as aa, outer as ab, projectVector as ac, dot2D as ad, projectVector2D as ae, gaussianAmplitude as af, gaussianWeight as ag, outer2D as ah, norm2D as ai, rowsToMat4 as aj, columnsToMat4 as ak, columnsToMat3 as al, LUFactor3x3 as am, LUSolve3x3 as an, linearSolve3x3 as ao, multiply3x3_mat3 as ap, transpose3x3 as aq, invert3x3 as ar, identity3x3 as as, isIdentity as at, isIdentity3x3 as au, quaternionToMatrix3x3 as av, roundNumber as aw, matrix3x3ToQuaternion as ax, multiplyQuaternion as ay, orthogonalize3x3 as az, roundVector as b, clampVector as c, dot as d, distance2BetweenPoints as e, vtkMath as f, solveLinearSystem as g, hsv2rgb as h, isNan as i, cross as j, add as k, normalize as l, multiplyAccumulate as m, norm as n, determinant2x2 as o, jacobiN as p, perpendiculars as q, radiansFromDegrees as r, subtract as s, jacobi as t, uninitializeBounds as u, vtkMath$1 as v, multiplyScalar as w, random as x, determinant3x3 as y, rowsToMat3 as z };
@@ -1,4 +1,4 @@
1
1
  import 'seedrandom';
2
2
  import '../../macros2.js';
3
3
  import './Math/Constants.js';
4
- export { an as LUFactor3x3, ao as LUSolve3x3, Y as Pi, k as add, V as angleBetweenVectors, T as areBoundsInitialized, B as areEquals, a as areMatricesEqual, a1 as arrayMax, a0 as arrayMin, D as arrayRange, a5 as beginCombination, a4 as binomial, aS as boundsIsWithinOtherBounds, Z as ceil, a2 as ceilLog2, aO as clampAndNormalizeValue, C as clampValue, c as clampVector, am as columnsToMat3, al as columnsToMat4, aN as computeBoundsFromPoints, X as createArray, F as createUninitializedBounds, j as cross, f as default, A as degreesFromRadians, o as determinant2x2, y as determinant3x3, aA as diagonalize3x3, e as distance2BetweenPoints, d as dot, ae as dot2D, aF as estimateMatrixCondition, aR as extentIsWithinOtherExtent, a3 as factorial, a$ as float2CssRGBA, a_ as floatRGB2HexCode, aZ as floatToHex2, J as floor, a9 as gaussian, ag as gaussianAmplitude, ah as gaussianWeight, aQ as getAdjustedScalarRange, E as getMajorAxisIndex, aP as getScalarTypeFittingRange, a8 as getSeed, S as getSparseOrthogonalMatrix, aI as hex2float, h as hsv2rgb, H as identity, at as identity3x3, aV as inf, as as invert3x3, aE as invertMatrix, aX as isFinite, au as isIdentity, G as isIdentity3x3, K as isInf, aY as isNaN, i as isNan, U as isPowerOfTwo, t as jacobi, p as jacobiN, N as lab2rgb, aJ as lab2xyz, ap as linearSolve3x3, aC as luFactorLinearSystem, aD as luSolveLinearSystem, ax as matrix3x3ToQuaternion, $ as max, _ as min, aq as multiply3x3_mat3, R as multiply3x3_vect3, m as multiplyAccumulate, ab as multiplyAccumulate2D, I as multiplyMatrix, ay as multiplyQuaternion, w as multiplyScalar, aa as multiplyScalar2D, Q as nearestPowerOfTwo, aW as negInf, a6 as nextCombination, n as norm, aj as norm2D, l as normalize, P as normalize2D, az as orthogonalize3x3, ac as outer, ai as outer2D, q as perpendiculars, aT as pointIsWithinBounds, ad as projectVector, af as projectVector2D, av as quaternionToMatrix3x3, r as radiansFromDegrees, x as random, a7 as randomSeed, L as rgb2hsv, M as rgb2lab, aM as rgb2xyz, O as round, aw as roundNumber, b as roundVector, z as rowsToMat3, ak as rowsToMat4, W as signedAngleBetweenVectors, aB as singularValueDecomposition3x3, aU as solve3PointCircle, aG as solveHomogeneousLeastSquares, aH as solveLeastSquares, g as solveLinearSystem, s as subtract, ar as transpose3x3, u as uninitializeBounds, aK as xyz2lab, aL as xyz2rgb } from './Math/index.js';
4
+ export { am as LUFactor3x3, an as LUSolve3x3, X as Pi, k as add, U as angleBetweenVectors, S as areBoundsInitialized, B as areEquals, a as areMatricesEqual, a0 as arrayMax, $ as arrayMin, D as arrayRange, a4 as beginCombination, a3 as binomial, aS as boundsIsWithinOtherBounds, Y as ceil, a1 as ceilLog2, aO as clampAndNormalizeValue, C as clampValue, c as clampVector, al as columnsToMat3, ak as columnsToMat4, aN as computeBoundsFromPoints, W as createArray, F as createUninitializedBounds, j as cross, f as default, A as degreesFromRadians, o as determinant2x2, y as determinant3x3, aA as diagonalize3x3, e as distance2BetweenPoints, d as dot, ad as dot2D, aF as estimateMatrixCondition, aR as extentIsWithinOtherExtent, a2 as factorial, a$ as float2CssRGBA, a_ as floatRGB2HexCode, aZ as floatToHex2, I as floor, a8 as gaussian, af as gaussianAmplitude, ag as gaussianWeight, aQ as getAdjustedScalarRange, E as getMajorAxisIndex, aP as getScalarTypeFittingRange, a7 as getSeed, R as getSparseOrthogonalMatrix, aI as hex2float, h as hsv2rgb, G as identity, as as identity3x3, aV as inf, ar as invert3x3, aE as invertMatrix, aX as isFinite, at as isIdentity, au as isIdentity3x3, J as isInf, aY as isNaN, i as isNan, T as isPowerOfTwo, t as jacobi, p as jacobiN, M as lab2rgb, aJ as lab2xyz, ao as linearSolve3x3, aC as luFactorLinearSystem, aD as luSolveLinearSystem, ax as matrix3x3ToQuaternion, _ as max, Z as min, ap as multiply3x3_mat3, Q as multiply3x3_vect3, m as multiplyAccumulate, aa as multiplyAccumulate2D, H as multiplyMatrix, ay as multiplyQuaternion, w as multiplyScalar, a9 as multiplyScalar2D, P as nearestPowerOfTwo, aW as negInf, a5 as nextCombination, n as norm, ai as norm2D, l as normalize, O as normalize2D, az as orthogonalize3x3, ab as outer, ah as outer2D, q as perpendiculars, aT as pointIsWithinBounds, ac as projectVector, ae as projectVector2D, av as quaternionToMatrix3x3, r as radiansFromDegrees, x as random, a6 as randomSeed, K as rgb2hsv, L as rgb2lab, aM as rgb2xyz, N as round, aw as roundNumber, b as roundVector, z as rowsToMat3, aj as rowsToMat4, V as signedAngleBetweenVectors, aB as singularValueDecomposition3x3, aU as solve3PointCircle, aG as solveHomogeneousLeastSquares, aH as solveLeastSquares, g as solveLinearSystem, s as subtract, aq as transpose3x3, u as uninitializeBounds, aK as xyz2lab, aL as xyz2rgb } from './Math/index.js';
@@ -5,10 +5,9 @@ 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, e as distance2BetweenPoints } from '../../Common/Core/Math/index.js';
8
+ import { l as normalize, 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
- import vtkMatrixBuilder from '../../Common/Core/MatrixBuilder.js';
12
11
  import vtkBox from '../../Common/DataModel/Box.js';
13
12
 
14
13
  // ----------------------------------------------------------------------------
@@ -212,16 +211,11 @@ function vtkCellPicker(publicAPI, model) {
212
211
  let tMin = Number.MAX_VALUE;
213
212
  const mapper = volume.getMapper();
214
213
  const imageData = mapper.getInputData();
215
- const origin = imageData.getOrigin();
216
- const spacing = imageData.getSpacing();
217
214
  const dims = imageData.getDimensions();
218
215
  const scalars = imageData.getPointData().getScalars().getData();
219
216
  const extent = imageData.getExtent();
220
- const direction = imageData.getDirection();
221
- let imageTransform;
222
- if (!isIdentity3x3(direction)) {
223
- imageTransform = vtkMatrixBuilder.buildFromRadian().translate(origin[0], origin[1], origin[2]).multiply3x3(direction).translate(-origin[0], -origin[1], -origin[2]).invert().getMatrix();
224
- }
217
+ // get the world to index transform to correctly transform from world to volume index
218
+ const imageTransform = imageData.getWorldToIndex();
225
219
 
226
220
  // calculate opacity table
227
221
  const numIComps = 1;
@@ -245,8 +239,8 @@ function vtkCellPicker(publicAPI, model) {
245
239
  const scale = oWidth / (oRange[1] - oRange[0] + 1);
246
240
 
247
241
  // Make a new p1 and p2 using the clipped t1 and t2
248
- const q1 = [0, 0, 0];
249
- const q2 = [0, 0, 0];
242
+ const q1 = [0, 0, 0, 1];
243
+ const q2 = [0, 0, 0, 1];
250
244
  q1[0] = p1[0];
251
245
  q1[1] = p1[1];
252
246
  q1[2] = p1[2];
@@ -259,13 +253,13 @@ function vtkCellPicker(publicAPI, model) {
259
253
  q2[j] = p1[j] * (1.0 - t2) + p2[j] * t2;
260
254
  }
261
255
  }
262
- const x1 = [0, 0, 0];
263
- const x2 = [0, 0, 0];
264
- for (let i = 0; i < 3; i++) {
265
- x1[i] = (q1[i] - origin[i]) / spacing[i];
266
- x2[i] = (q2[i] - origin[i]) / spacing[i];
267
- }
268
- const x = [0, 0, 0, 0];
256
+
257
+ // convert q1, q2 world coordinates to x1, x2 volume index coordinates
258
+ const x1 = [0, 0, 0, 0];
259
+ const x2 = [0, 0, 0, 0];
260
+ vec4.transformMat4(x1, q1, imageTransform);
261
+ vec4.transformMat4(x2, q2, imageTransform);
262
+ const x = [0, 0, 0];
269
263
  const xi = [0, 0, 0];
270
264
  const sliceSize = dims[1] * dims[0];
271
265
  const rowSize = dims[0];
@@ -281,10 +275,6 @@ function vtkCellPicker(publicAPI, model) {
281
275
  // "t" is the fractional distance between endpoints x1 and x2
282
276
  x[j] = x1[j] * (1.0 - t) + x2[j] * t;
283
277
  }
284
- x[3] = 1.0;
285
- if (imageTransform) {
286
- vec4.transformMat4(x, x, imageTransform);
287
- }
288
278
  for (let j = 0; j < 3; j++) {
289
279
  // Bounds check
290
280
  if (x[j] < extent[2 * j]) {
@@ -1,4 +1,4 @@
1
- import { H as identity, I as multiplyMatrix } from '../../../Common/Core/Math/index.js';
1
+ import { G as identity, H as multiplyMatrix } from '../../../Common/Core/Math/index.js';
2
2
 
3
3
  /**
4
4
  * A helper file to transform RGBA points using CSS filters equivalent
@@ -1,5 +1,5 @@
1
1
  import { m as macro } from '../../macros2.js';
2
- import { h as hsv2rgb, i as isNan, J as floor, K as isInf, L as rgb2hsv, M as rgb2lab, N as lab2rgb } from '../../Common/Core/Math/index.js';
2
+ import { h as hsv2rgb, i as isNan, I as floor, J as isInf, K as rgb2hsv, L as rgb2lab, M as lab2rgb } from '../../Common/Core/Math/index.js';
3
3
  import vtkScalarsToColors from '../../Common/Core/ScalarsToColors.js';
4
4
  import Constants from './ColorTransferFunction/Constants.js';
5
5
 
@@ -1,6 +1,6 @@
1
1
  import { m as macro } from '../../macros2.js';
2
2
  import Constants from './Coordinate/Constants.js';
3
- import { O as round, J as floor } from '../../Common/Core/Math/index.js';
3
+ import { N as round, I as floor } from '../../Common/Core/Math/index.js';
4
4
 
5
5
  const {
6
6
  Coordinate
@@ -1,6 +1,6 @@
1
1
  import { vec3, mat4 } from 'gl-matrix';
2
2
  import * as d3 from 'd3-scale';
3
- import { P as normalize2D, Q as nearestPowerOfTwo } from '../../Common/Core/Math/index.js';
3
+ import { O as normalize2D, P as nearestPowerOfTwo } from '../../Common/Core/Math/index.js';
4
4
  import { m as macro } from '../../macros2.js';
5
5
  import vtkActor from './Actor.js';
6
6
  import vtkBoundingBox from '../../Common/DataModel/BoundingBox.js';
@@ -2,7 +2,7 @@ import Constants from './ImageMapper/Constants.js';
2
2
  import { m as macro } from '../../macros2.js';
3
3
  import vtkAbstractImageMapper from './AbstractImageMapper.js';
4
4
  import { intersectWithLineForPointPicking, intersectWithLineForCellPicking } from './AbstractImageMapper/helper.js';
5
- import { C as clampValue, R as multiply3x3_vect3, F as createUninitializedBounds, S as getSparseOrthogonalMatrix } from '../../Common/Core/Math/index.js';
5
+ import { C as clampValue, Q as multiply3x3_vect3, F as createUninitializedBounds, R as getSparseOrthogonalMatrix } from '../../Common/Core/Math/index.js';
6
6
  import CoincidentTopologyHelper from './Mapper/CoincidentTopologyHelper.js';
7
7
 
8
8
  const {
@@ -2,7 +2,7 @@ import { mat4, vec3 } from 'gl-matrix';
2
2
  import { n as newInstance$1, g as get, e as setGet, k as getArray, l as setGetArray, i as moveToProtected, c as macro } from '../../macros2.js';
3
3
  import vtkCamera from './Camera.js';
4
4
  import vtkLight from './Light.js';
5
- import { T as areBoundsInitialized, u as uninitializeBounds, r as radiansFromDegrees, d as dot, F as createUninitializedBounds } from '../../Common/Core/Math/index.js';
5
+ import { S as areBoundsInitialized, u as uninitializeBounds, r as radiansFromDegrees, d as dot, F as createUninitializedBounds } from '../../Common/Core/Math/index.js';
6
6
  import vtkViewport from './Viewport.js';
7
7
  import vtkBoundingBox from '../../Common/DataModel/BoundingBox.js';
8
8
 
@@ -1,5 +1,5 @@
1
1
  import * as d3 from 'd3-scale';
2
- import { Q as nearestPowerOfTwo } from '../../Common/Core/Math/index.js';
2
+ import { P as nearestPowerOfTwo } from '../../Common/Core/Math/index.js';
3
3
  import { m as macro } from '../../macros2.js';
4
4
  import vtkActor from './Actor.js';
5
5
  import vtkDataArray from '../../Common/Core/DataArray.js';
@@ -1,5 +1,5 @@
1
1
  import { m as macro } from '../../macros2.js';
2
- import { F as createUninitializedBounds, C as clampValue, J as floor } from '../../Common/Core/Math/index.js';
2
+ import { F as createUninitializedBounds, C as clampValue, I as floor } from '../../Common/Core/Math/index.js';
3
3
  import Constants from './VolumeMapper/Constants.js';
4
4
  import vtkAbstractMapper3D from './AbstractMapper3D.js';
5
5
  import vtkPiecewiseFunction from '../../Common/DataModel/PiecewiseFunction.js';
@@ -8,7 +8,7 @@ import { v as vtkPolyData2DVS } from './glsl/vtkPolyData2DVS.glsl.js';
8
8
  import vtkReplacementShaderMapper from './ReplacementShaderMapper.js';
9
9
  import vtkShaderProgram from './ShaderProgram.js';
10
10
  import vtkViewNode from '../SceneGraph/ViewNode.js';
11
- import { O as round } from '../../Common/Core/Math/index.js';
11
+ import { N as round } from '../../Common/Core/Math/index.js';
12
12
  import { DisplayLocation } from '../Core/Property2D/Constants.js';
13
13
  import { registerOverride } from './ViewNodeFactory.js';
14
14
 
@@ -2,7 +2,7 @@ import Constants from './Texture/Constants.js';
2
2
  import HalfFloat from '../../Common/Core/HalfFloat.js';
3
3
  import { n as newInstance$1, o as obj, s as set, e as setGet, g as get, i as moveToProtected, a as newTypedArray, c as macro } from '../../macros2.js';
4
4
  import vtkDataArray from '../../Common/Core/DataArray.js';
5
- import { U as isPowerOfTwo, Q as nearestPowerOfTwo } from '../../Common/Core/Math/index.js';
5
+ import { T as isPowerOfTwo, P as nearestPowerOfTwo } from '../../Common/Core/Math/index.js';
6
6
  import vtkViewNode from '../SceneGraph/ViewNode.js';
7
7
  import { registerOverride } from './ViewNodeFactory.js';
8
8
 
@@ -49,11 +49,37 @@ export interface vtkAbstractManipulator extends vtkObject {
49
49
  setUseCameraNormal(useCameraNormal: boolean): boolean;
50
50
 
51
51
  /**
52
- *
52
+ * Processes a vtkRenderWindowInteractor event into 3D world positional info.
53
+ *
54
+ * Returns an object containing:
55
+ * - worldCoords: a 3D coordinate corresponding to the 2D event.
56
+ * - worldDelta: a 3D position delta between the current and the previous call to handleEvent.
57
+ * - worldDirection: a 3D directional vector. Only on select manipulators.
58
+ *
59
+ * worldCoords can be null if the pointer event enters an invalid manipulator region. For example,
60
+ * the PickerManipulator returns null when the pointer event is off of the picked geometry.
61
+ *
62
+ * worldDelta only makes sense between two calls of `handleEvent`. In a queue of `handleEvent` calls,
63
+ * the i-th call returns the delta between the i-th worldCoords and the (i-1)-th worldCoords.
64
+ * Thus, calling `handleEvent` is necessary for maintaining a valid worldDelta even when the return
65
+ * value is ignored.
66
+ *
67
+ * There are three cases where worldDelta needs to handle null events:
68
+ * 1. the first call to `handleEvent`, since there is no previously cached event position.
69
+ * worldDelta is set to [0, 0, 0].
70
+ * 2. if the current `handleEvent` call returns a null worldCoords. worldDelta is set to [0, 0, 0].
71
+ * 3. if the previous `handleEvent` call returned a null worldCoords. In this case, worldDelta is the
72
+ * delta between the current worldCoords and the previous non-null worldCoords, referring to the
73
+ * previous 2 cases when applicable.
74
+ *
53
75
  * @param callData
54
76
  * @param glRenderWindow
55
77
  */
56
- handleEvent(callData: any, glRenderWindow: vtkOpenGLRenderWindow): { worldCoords: Nullable<Vector3>, worldDirection?: Matrix3x3 };
78
+ handleEvent(callData: any, glRenderWindow: vtkOpenGLRenderWindow): {
79
+ worldCoords: Nullable<Vector3>,
80
+ worldDelta: Vector3,
81
+ worldDirection?: Matrix3x3,
82
+ };
57
83
 
58
84
  /* ------------------------------------------------------------------- */
59
85
 
@@ -1,4 +1,5 @@
1
1
  import { m as macro } from '../../macros2.js';
2
+ import { s as subtract } from '../../Common/Core/Math/index.js';
2
3
 
3
4
  // ----------------------------------------------------------------------------
4
5
  // vtkAbstractManipulator methods
@@ -7,6 +8,7 @@ import { m as macro } from '../../macros2.js';
7
8
  function vtkAbstractManipulator(publicAPI, model) {
8
9
  // Set our className
9
10
  model.classHierarchy.push('vtkAbstractManipulator');
11
+ model._prevWorldCoords = [];
10
12
  publicAPI.getOrigin = callData => {
11
13
  if (model.userOrigin) return model.userOrigin;
12
14
  if (model.useCameraFocalPoint) return callData.pokedRenderer.getActiveCamera().getFocalPoint();
@@ -21,6 +23,24 @@ function vtkAbstractManipulator(publicAPI, model) {
21
23
  if (model.widgetNormal) return model.widgetNormal;
22
24
  return [0, 0, 1];
23
25
  };
26
+ model._computeDeltaFromPrevCoords = curWorldCoords => {
27
+ if (!model._prevWorldCoords?.length || !curWorldCoords?.length) return [0, 0, 0];
28
+ return subtract(curWorldCoords, model._prevWorldCoords, []);
29
+ };
30
+ model._addWorldDeltas = manipulatorResults => {
31
+ const {
32
+ worldCoords: curWorldCoords
33
+ } = manipulatorResults;
34
+ const worldDelta = model._computeDeltaFromPrevCoords(curWorldCoords);
35
+ if (curWorldCoords) model._prevWorldCoords = curWorldCoords;
36
+ const deltas = {
37
+ worldDelta
38
+ };
39
+ return {
40
+ ...manipulatorResults,
41
+ ...deltas
42
+ };
43
+ };
24
44
  }
25
45
 
26
46
  // ----------------------------------------------------------------------------
@@ -19,9 +19,9 @@ function vtkCPRManipulator(publicAPI, model) {
19
19
  publicAPI.handleEvent = (callData, glRenderWindow) => {
20
20
  const mapper = model.cprActor?.getMapper();
21
21
  if (!mapper) {
22
- return {
22
+ return model._addWorldDeltas({
23
23
  worldCoords: null
24
- };
24
+ });
25
25
  }
26
26
 
27
27
  // Get normal and origin of the picking plane from the actor matrix
@@ -38,7 +38,7 @@ function vtkCPRManipulator(publicAPI, model) {
38
38
  vec3.transformMat4(modelPlanePicking, worldPlanePicking, inversecprActorMatrix);
39
39
  const height = mapper.getHeight();
40
40
  const distance = height - modelPlanePicking[1];
41
- return publicAPI.distanceEvent(distance);
41
+ return model._addWorldDeltas(publicAPI.distanceEvent(distance));
42
42
  };
43
43
  publicAPI.distanceEvent = distance => {
44
44
  const mapper = model.cprActor?.getMapper();
@@ -36,7 +36,7 @@ function projectDisplayToLine(x, y, lineOrigin, lineDirection, renderer, glRende
36
36
  function vtkLineManipulator(publicAPI, model) {
37
37
  // Set our className
38
38
  model.classHierarchy.push('vtkLineManipulator');
39
- publicAPI.handleEvent = (callData, glRenderWindow) => ({
39
+ publicAPI.handleEvent = (callData, glRenderWindow) => model._addWorldDeltas({
40
40
  worldCoords: projectDisplayToLine(callData.position.x, callData.position.y, publicAPI.getOrigin(callData), publicAPI.getNormal(callData), callData.pokedRenderer, glRenderWindow)
41
41
  });
42
42
  }
@@ -20,9 +20,9 @@ function vtkPickerManipulator(publicAPI, model) {
20
20
  } else {
21
21
  model.position = null;
22
22
  }
23
- return {
23
+ return model._addWorldDeltas({
24
24
  worldCoords: model.position
25
- };
25
+ });
26
26
  };
27
27
  }
28
28
 
@@ -15,7 +15,7 @@ function intersectDisplayWithPlane(x, y, planeOrigin, planeNormal, renderer, glR
15
15
  function vtkPlaneManipulator(publicAPI, model) {
16
16
  // Set our className
17
17
  model.classHierarchy.push('vtkPlaneManipulator');
18
- publicAPI.handleEvent = (callData, glRenderWindow) => ({
18
+ publicAPI.handleEvent = (callData, glRenderWindow) => model._addWorldDeltas({
19
19
  worldCoords: intersectDisplayWithPlane(callData.position.x, callData.position.y, publicAPI.getOrigin(callData), publicAPI.getNormal(callData), callData.pokedRenderer, glRenderWindow)
20
20
  });
21
21
  }
@@ -36,9 +36,9 @@ function vtkTrackballManipulator(publicAPI, model) {
36
36
  const newDirection = trackballRotate(prevX, prevY, callData.position.x, callData.position.y, publicAPI.getOrigin(callData), publicAPI.getNormal(callData), callData.pokedRenderer);
37
37
  prevX = callData.position.x;
38
38
  prevY = callData.position.y;
39
- return {
39
+ return model._addWorldDeltas({
40
40
  worldCoords: newDirection
41
- };
41
+ });
42
42
  };
43
43
  publicAPI.reset = callData => {
44
44
  prevX = callData.position.x;
@@ -1,4 +1,5 @@
1
1
  import { m as macro } from '../../../macros2.js';
2
+ import { k as add } from '../../../Common/Core/Math/index.js';
2
3
  import vtkPointPicker from '../../../Rendering/Core/PointPicker.js';
3
4
 
4
5
  const MAX_POINTS = 3;
@@ -33,10 +34,10 @@ function widgetBehavior(publicAPI, model) {
33
34
  picker.initializePickList();
34
35
  picker.setPickList(publicAPI.getNestedProps());
35
36
  const manipulator = model.activeState?.getManipulator?.() ?? model.manipulator;
37
+ const {
38
+ worldCoords
39
+ } = manipulator.handleEvent(e, model._apiSpecificRenderWindow);
36
40
  if (model.activeState === model.widgetState.getMoveHandle() && model.widgetState.getHandleList().length < MAX_POINTS && manipulator) {
37
- const {
38
- worldCoords
39
- } = manipulator.handleEvent(e, model._apiSpecificRenderWindow);
40
41
  // Commit handle to location
41
42
  const moveHandle = model.widgetState.getMoveHandle();
42
43
  moveHandle.setOrigin(...worldCoords);
@@ -62,11 +63,17 @@ function widgetBehavior(publicAPI, model) {
62
63
  const manipulator = model.activeState?.getManipulator?.() ?? model.manipulator;
63
64
  if (manipulator && model.pickable && model.dragable && model.activeState && model.activeState.getActive() && !ignoreKey(callData)) {
64
65
  const {
65
- worldCoords
66
+ worldCoords,
67
+ worldDelta
66
68
  } = manipulator.handleEvent(callData, model._apiSpecificRenderWindow);
67
- if (worldCoords.length && (model.activeState === model.widgetState.getMoveHandle() || model._isDragging) && model.activeState.setOrigin // e.g. the line is pickable but not draggable
68
- ) {
69
- model.activeState.setOrigin(worldCoords);
69
+ const isHandleMoving = model.activeState === model.widgetState.getMoveHandle() || model._isDragging;
70
+ if (isHandleMoving && worldCoords.length && model.activeState.setOrigin) {
71
+ const curOrigin = model.activeState.getOrigin();
72
+ if (curOrigin) {
73
+ model.activeState.setOrigin(add(curOrigin, worldDelta, []));
74
+ } else {
75
+ model.activeState.setOrigin(worldCoords);
76
+ }
70
77
  publicAPI.invokeInteractionEvent();
71
78
  return macro.EVENT_ABORT;
72
79
  }
@@ -3,7 +3,7 @@ import vtkAbstractWidgetFactory from '../Core/AbstractWidgetFactory.js';
3
3
  import vtkPlanePointManipulator from '../Manipulators/PlaneManipulator.js';
4
4
  import vtkPolyLineRepresentation from '../Representations/PolyLineRepresentation.js';
5
5
  import vtkSphereHandleRepresentation from '../Representations/SphereHandleRepresentation.js';
6
- import { s as subtract, V as angleBetweenVectors } from '../../Common/Core/Math/index.js';
6
+ import { s as subtract, U as angleBetweenVectors } from '../../Common/Core/Math/index.js';
7
7
  import widgetBehavior from './AngleWidget/behavior.js';
8
8
  import generateState from './AngleWidget/state.js';
9
9
  import { ViewTypes } from '../Core/WidgetManager/Constants.js';
@@ -1,14 +1,17 @@
1
1
  import { m as macro } from '../../../macros2.js';
2
+ import { k as add } from '../../../Common/Core/Math/index.js';
2
3
  import { handleTypeFromName, AXES, calculateCropperCenter, calculateDirection, transformVec3 } from './helpers.js';
3
4
 
4
5
  function widgetBehavior(publicAPI, model) {
5
6
  model._isDragging = false;
6
7
  publicAPI.setDisplayCallback = callback => model.representations[0].setDisplayCallback(callback);
7
- publicAPI.handleLeftButtonPress = () => {
8
+ publicAPI.handleLeftButtonPress = callData => {
8
9
  if (!model.activeState || !model.activeState.getActive() || !model.pickable) {
9
10
  return macro.VOID;
10
11
  }
11
12
  if (model.dragable) {
13
+ // updates worldDelta
14
+ model.activeState.getManipulator().handleEvent(callData, model._apiSpecificRenderWindow);
12
15
  model._isDragging = true;
13
16
  model._apiSpecificRenderWindow.setCursor('grabbing');
14
17
  model._interactor.requestAnimation(publicAPI);
@@ -42,16 +45,23 @@ function widgetBehavior(publicAPI, model) {
42
45
  const planes = model.widgetState.getCroppingPlanes().getPlanes();
43
46
  const indexToWorldT = model.widgetState.getIndexToWorldT();
44
47
  let worldCoords = [];
48
+ let worldDelta = [];
45
49
  if (type === 'corners') {
46
50
  // manipulator should be a plane manipulator
47
- worldCoords = manipulator.handleEvent(callData, model._apiSpecificRenderWindow).worldCoords;
51
+ ({
52
+ worldCoords,
53
+ worldDelta
54
+ } = manipulator.handleEvent(callData, model._apiSpecificRenderWindow));
48
55
  }
49
56
  if (type === 'faces') {
50
57
  // get center of current crop box
51
58
  const worldCenter = calculateCropperCenter(planes, indexToWorldT);
52
59
  manipulator.setHandleOrigin(worldCenter);
53
60
  manipulator.setHandleNormal(calculateDirection(model.activeState.getOrigin(), worldCenter));
54
- worldCoords = manipulator.handleEvent(callData, model._apiSpecificRenderWindow).worldCoords;
61
+ ({
62
+ worldCoords,
63
+ worldDelta
64
+ } = manipulator.handleEvent(callData, model._apiSpecificRenderWindow));
55
65
  }
56
66
  if (type === 'edges') {
57
67
  // constrain to a plane with a normal parallel to the edge
@@ -61,9 +71,12 @@ function widgetBehavior(publicAPI, model) {
61
71
  // get center of current crop box
62
72
  const worldCenter = calculateCropperCenter(planes, indexToWorldT);
63
73
  manipulator.setHandleNormal(calculateDirection(handle.getOrigin(), worldCenter));
64
- worldCoords = manipulator.handleEvent(callData, model._apiSpecificRenderWindow).worldCoords;
74
+ ({
75
+ worldCoords,
76
+ worldDelta
77
+ } = manipulator.handleEvent(callData, model._apiSpecificRenderWindow));
65
78
  }
66
- if (worldCoords.length) {
79
+ if (worldCoords.length && worldDelta.length) {
67
80
  // transform worldCoords to indexCoords, and then update the croppingPlanes() state with setPlanes().
68
81
  const worldToIndexT = model.widgetState.getWorldToIndexT();
69
82
  const indexCoords = transformVec3(worldCoords, worldToIndexT);
@@ -74,7 +87,7 @@ function widgetBehavior(publicAPI, model) {
74
87
  planes[i * 2 + 1] = indexCoords[i];
75
88
  }
76
89
  }
77
- model.activeState.setOrigin(...worldCoords);
90
+ model.activeState.setOrigin(add(model.activeState.getOrigin(), worldDelta, []));
78
91
  model.widgetState.getCroppingPlanes().setPlanes(...planes);
79
92
  return macro.EVENT_ABORT;
80
93
  }
@@ -1,4 +1,5 @@
1
1
  import { m as macro } from '../../macros2.js';
2
+ import { k as add } from '../../Common/Core/Math/index.js';
2
3
  import vtkAbstractWidgetFactory from '../Core/AbstractWidgetFactory.js';
3
4
  import vtkImplicitPlaneRepresentation from '../Representations/ImplicitPlaneRepresentation.js';
4
5
  import vtkLineManipulator from '../Manipulators/LineManipulator.js';
@@ -13,6 +14,8 @@ import { ViewTypes } from '../Core/WidgetManager/Constants.js';
13
14
  function widgetBehavior(publicAPI, model) {
14
15
  model.classHierarchy.push('vtkPlaneWidget');
15
16
  model._isDragging = false;
17
+ // used to track the constrained widget position
18
+ model._draggingWidgetOrigin = [0, 0, 0];
16
19
  publicAPI.setDisplayCallback = callback => model.representations[0].setDisplayCallback(callback);
17
20
  publicAPI.updateCursor = () => {
18
21
  switch (model.activeState.getUpdateMethodName()) {
@@ -38,7 +41,11 @@ function widgetBehavior(publicAPI, model) {
38
41
  model.planeManipulator.setWidgetOrigin(model.widgetState.getOrigin());
39
42
  model.trackballManipulator.reset(callData); // setup trackball delta
40
43
 
44
+ // updates worldDelta
45
+ model.lineManipulator.handleEvent(callData, model._apiSpecificRenderWindow);
46
+ model.planeManipulator.handleEvent(callData, model._apiSpecificRenderWindow);
41
47
  if (model.dragable) {
48
+ model._draggingWidgetOrigin = model.widgetState.getOrigin();
42
49
  model._isDragging = true;
43
50
  model._apiSpecificRenderWindow.setCursor('grabbing');
44
51
  model._interactor.requestAnimation(publicAPI);
@@ -80,10 +87,14 @@ function widgetBehavior(publicAPI, model) {
80
87
  publicAPI.updateFromOrigin = callData => {
81
88
  model.planeManipulator.setWidgetNormal(model.widgetState.getNormal());
82
89
  const {
83
- worldCoords
90
+ worldCoords,
91
+ worldDelta
84
92
  } = model.planeManipulator.handleEvent(callData, model._apiSpecificRenderWindow);
85
- if (model.widgetState.containsPoint(worldCoords)) {
86
- model.activeState.setOrigin(worldCoords);
93
+ add(model._draggingWidgetOrigin, worldDelta, model._draggingWidgetOrigin);
94
+
95
+ // test containment of interaction coords
96
+ if (model.widgetState.containsPoint(...worldCoords)) {
97
+ model.activeState.setOrigin(model._draggingWidgetOrigin);
87
98
  }
88
99
  };
89
100
 
@@ -93,10 +104,11 @@ function widgetBehavior(publicAPI, model) {
93
104
  // Move origin along normal axis
94
105
  model.lineManipulator.setWidgetNormal(model.activeState.getNormal());
95
106
  const {
96
- worldCoords
107
+ worldDelta
97
108
  } = model.lineManipulator.handleEvent(callData, model._apiSpecificRenderWindow);
98
- if (model.widgetState.containsPoint(...worldCoords)) {
99
- model.activeState.setOrigin(worldCoords);
109
+ add(model._draggingWidgetOrigin, worldDelta, model._draggingWidgetOrigin);
110
+ if (model.widgetState.containsPoint(...model._draggingWidgetOrigin)) {
111
+ model.activeState.setOrigin(model._draggingWidgetOrigin);
100
112
  }
101
113
  };
102
114
 
@@ -1,4 +1,5 @@
1
1
  import { m as macro } from '../../../macros2.js';
2
+ import { k as add } from '../../../Common/Core/Math/index.js';
2
3
 
3
4
  function widgetBehavior(publicAPI, model) {
4
5
  model.classHierarchy.push('vtkLabelWidgetProp');
@@ -37,10 +38,10 @@ function widgetBehavior(publicAPI, model) {
37
38
  return macro.VOID;
38
39
  }
39
40
  const manipulator = model.activeState?.getManipulator?.() ?? model.manipulator;
41
+ const {
42
+ worldCoords
43
+ } = manipulator.handleEvent(e, model._apiSpecificRenderWindow);
40
44
  if (model.activeState === model.widgetState.getMoveHandle() && manipulator) {
41
- const {
42
- worldCoords
43
- } = manipulator.handleEvent(e, model._apiSpecificRenderWindow);
44
45
  // Commit handle to location
45
46
  const moveHandle = model.widgetState.getMoveHandle();
46
47
  moveHandle.setOrigin(worldCoords);
@@ -87,14 +88,17 @@ function widgetBehavior(publicAPI, model) {
87
88
  const manipulator = model.activeState?.getManipulator?.() ?? model.manipulator;
88
89
  if (manipulator && model.pickable && model.dragable && model.activeState && model.activeState.getActive() && !ignoreKey(callData)) {
89
90
  const {
90
- worldCoords
91
+ worldCoords,
92
+ worldDelta
91
93
  } = manipulator.handleEvent(callData, model._apiSpecificRenderWindow);
92
- if (worldCoords.length && (model.activeState === model.widgetState.getMoveHandle() || model._isDragging)) {
93
- model.activeState.setOrigin(worldCoords);
94
- model.widgetState.getText().setOrigin(model.activeState.getOrigin());
95
- publicAPI.invokeInteractionEvent();
96
- return macro.EVENT_ABORT;
97
- }
94
+ const isHandleMoving = model.widgetState.getMoveHandle() === model.activeState || model._isDragging;
95
+ if (!isHandleMoving || !worldCoords.length || !worldDelta.length) return macro.VOID;
96
+ const curOrigin = model.activeState.getOrigin();
97
+ const newOrigin = curOrigin ? add(curOrigin, worldDelta, []) : worldCoords;
98
+ model.activeState.setOrigin(newOrigin);
99
+ model.widgetState.getText().setOrigin(newOrigin);
100
+ publicAPI.invokeInteractionEvent();
101
+ return macro.EVENT_ABORT;
98
102
  }
99
103
  return macro.VOID;
100
104
  };
@@ -1,6 +1,6 @@
1
1
  import Constants from './Constants.js';
2
2
  import { m as macro } from '../../../macros2.js';
3
- import { s as subtract, k as add, l as normalize } from '../../../Common/Core/Math/index.js';
3
+ import { k as add, s as subtract, l as normalize } from '../../../Common/Core/Math/index.js';
4
4
  import { getNumberOfPlacedHandles, isHandlePlaced, calculateTextPosition, updateTextPosition, getPoint } from './helpers.js';
5
5
 
6
6
  const {
@@ -47,7 +47,7 @@ function widgetBehavior(publicAPI, model) {
47
47
  function updateCursor(callData) {
48
48
  model._isDragging = true;
49
49
  const manipulator = model.activeState?.getManipulator?.() ?? model.manipulator;
50
- model.previousPosition = manipulator.handleEvent(callData, model._apiSpecificRenderWindow).worldCoords;
50
+ manipulator.handleEvent(callData, model._apiSpecificRenderWindow);
51
51
  model._apiSpecificRenderWindow.setCursor('grabbing');
52
52
  model._interactor.requestAnimation(publicAPI);
53
53
  }
@@ -181,22 +181,32 @@ function widgetBehavior(publicAPI, model) {
181
181
  const manipulator = model.activeState?.getManipulator?.() ?? model.manipulator;
182
182
  if (manipulator && model.pickable && model.dragable && model.activeState && model.activeState.getActive() && !ignoreKey(callData)) {
183
183
  const {
184
- worldCoords
184
+ worldCoords,
185
+ worldDelta
185
186
  } = manipulator.handleEvent(callData, model._apiSpecificRenderWindow);
186
- const translation = model.previousPosition ? subtract(worldCoords, model.previousPosition, []) : [0, 0, 0];
187
- model.previousPosition = worldCoords;
188
- if (
187
+ const isHandleMoving =
189
188
  // is placing first or second handle
190
189
  model.activeState === model.widgetState.getMoveHandle() ||
191
190
  // is dragging already placed first or second handle
192
- model._isDragging) {
193
- if (model.activeState.setOrigin) {
194
- model.activeState.setOrigin(worldCoords);
191
+ model._isDragging;
192
+
193
+ // the line state doesn't have setOrigin
194
+ const isDraggingLine = !model.activeState.setOrigin;
195
+ if (isHandleMoving) {
196
+ if (!isDraggingLine) {
197
+ const curOrigin = model.activeState.getOrigin();
198
+ if (curOrigin) {
199
+ model.activeState.setOrigin(add(model.activeState.getOrigin(), worldDelta, []));
200
+ } else {
201
+ model.activeState.setOrigin(worldCoords);
202
+ }
195
203
  publicAPI.updateHandleVisibility(publicAPI.getHandleIndex(model.activeState));
196
204
  } else {
197
- // Dragging line
198
- publicAPI.getHandle(0).setOrigin(add(publicAPI.getHandle(0).getOrigin(), translation, []));
199
- publicAPI.getHandle(1).setOrigin(add(publicAPI.getHandle(1).getOrigin(), translation, []));
205
+ // Dragging line; move all handles
206
+ for (let i = 0; i < 2; i++) {
207
+ const handleOrigin = publicAPI.getHandle(i).getOrigin();
208
+ publicAPI.getHandle(i).setOrigin(add(handleOrigin, worldDelta, []));
209
+ }
200
210
  }
201
211
  publicAPI.updateHandleOrientations();
202
212
  updateTextPosition(model);
@@ -1,4 +1,5 @@
1
1
  import { m as macro } from '../../../macros2.js';
2
+ import { k as add } from '../../../Common/Core/Math/index.js';
2
3
 
3
4
  function widgetBehavior(publicAPI, model) {
4
5
  model.classHierarchy.push('vtkPolyLineWidgetProp');
@@ -23,11 +24,20 @@ function widgetBehavior(publicAPI, model) {
23
24
  return macro.VOID;
24
25
  }
25
26
  const {
26
- worldCoords
27
+ worldCoords,
28
+ worldDelta
27
29
  } = manipulator.handleEvent(callData, model._apiSpecificRenderWindow);
28
- if (worldCoords.length && (model.activeState === model.widgetState.getMoveHandle() || model._isDragging) && model.activeState.setOrigin // e.g. the line is pickable but not draggable
29
- ) {
30
- model.activeState.setOrigin(worldCoords);
30
+ const isHandleMoving = model.activeState === model.widgetState.getMoveHandle() || model._isDragging;
31
+
32
+ // the line is pickable but not draggable
33
+ const isPickingLine = !model.activeState.setOrigin;
34
+ if (worldCoords.length && isHandleMoving && !isPickingLine) {
35
+ const curOrigin = model.activeState.getOrigin();
36
+ if (curOrigin) {
37
+ model.activeState.setOrigin(add(curOrigin, worldDelta, []));
38
+ } else {
39
+ model.activeState.setOrigin(worldCoords);
40
+ }
31
41
  publicAPI.invokeInteractionEvent();
32
42
  return macro.EVENT_ABORT;
33
43
  }
@@ -73,6 +83,8 @@ function widgetBehavior(publicAPI, model) {
73
83
  newHandle.setScale1(moveHandle.getScale1());
74
84
  newHandle.setManipulator(manipulator);
75
85
  } else if (model.dragable) {
86
+ // Update worldDelta
87
+ manipulator.handleEvent(e, model._apiSpecificRenderWindow);
76
88
  model._isDragging = true;
77
89
  model._apiSpecificRenderWindow.setCursor('grabbing');
78
90
  model._interactor.requestAnimation(publicAPI);
@@ -53,11 +53,6 @@ function vtkPolyLineWidget(publicAPI, model) {
53
53
  // initialization
54
54
  // --------------------------------------------------------------------------
55
55
 
56
- model.widgetState.onBoundsChange(bounds => {
57
- const center = [(bounds[0] + bounds[1]) * 0.5, (bounds[2] + bounds[3]) * 0.5, (bounds[4] + bounds[5]) * 0.5];
58
- model.widgetState.getMoveHandle().setOrigin(center);
59
- });
60
-
61
56
  // Default manipulator
62
57
  publicAPI.setManipulator(model.manipulator || vtkPlanePointManipulator.newInstance({
63
58
  useCameraFocalPoint: true,
@@ -1,7 +1,7 @@
1
1
  import { m as macro } from '../../../macros2.js';
2
2
  import vtkBoundingBox from '../../../Common/DataModel/BoundingBox.js';
3
3
  import vtkLine from '../../../Common/DataModel/Line.js';
4
- import { k as add, l as normalize, s as subtract, d as dot, j as cross, m as multiplyAccumulate, w as multiplyScalar, W as signedAngleBetweenVectors } from '../../../Common/Core/Math/index.js';
4
+ import { k as add, l as normalize, s as subtract, d as dot, j as cross, m as multiplyAccumulate, w as multiplyScalar, V as signedAngleBetweenVectors } from '../../../Common/Core/Math/index.js';
5
5
  import { getLineNames, getOtherLineName, updateState, boundPointOnPlane, getLinePlaneName, getLineInPlaneName, rotateVector } from './helpers.js';
6
6
  import { InteractionMethodsName, ScrollingMethods, planeNameToViewType } from './Constants.js';
7
7
 
@@ -2,7 +2,7 @@ import vtkBoundingBox, { STATIC } from '../../../Common/DataModel/BoundingBox.js
2
2
  import vtkCubeSource from '../../../Filters/Sources/CubeSource.js';
3
3
  import vtkCutter from '../../../Filters/Core/Cutter.js';
4
4
  import vtkPlane from '../../../Common/DataModel/Plane.js';
5
- import { s as subtract, l as normalize, j as cross, w as multiplyScalar, m as multiplyAccumulate, W as signedAngleBetweenVectors } from '../../../Common/Core/Math/index.js';
5
+ import { s as subtract, l as normalize, j as cross, w as multiplyScalar, m as multiplyAccumulate, V as signedAngleBetweenVectors } from '../../../Common/Core/Math/index.js';
6
6
  import vtkMatrixBuilder from '../../../Common/Core/MatrixBuilder.js';
7
7
  import { viewTypeToPlaneName, planeNameToViewType, planeNames } from './Constants.js';
8
8
 
@@ -5,7 +5,6 @@ function widgetBehavior(publicAPI, model) {
5
5
  const moveHandle = model.widgetState.getMoveHandle();
6
6
  moveHandle.setVisible(true);
7
7
  model._isDragging = false;
8
- model.previousPosition = null;
9
8
  function isValidHandle(handle) {
10
9
  return handle === moveHandle;
11
10
  }
@@ -32,7 +31,6 @@ function widgetBehavior(publicAPI, model) {
32
31
  if (model.activeState === moveHandle) {
33
32
  if (!moveHandle.getOrigin() && worldCoords) {
34
33
  moveHandle.setOrigin(worldCoords);
35
- model.previousPosition = [...worldCoords];
36
34
  }
37
35
  }
38
36
  model._isDragging = true;
@@ -46,7 +44,6 @@ function widgetBehavior(publicAPI, model) {
46
44
  return macro.VOID;
47
45
  }
48
46
  if (isPlaced()) {
49
- model.previousPosition = null;
50
47
  model._widgetManager.enablePicking();
51
48
  model._apiSpecificRenderWindow.setCursor('pointer');
52
49
  model._isDragging = false;
@@ -63,10 +60,7 @@ function widgetBehavior(publicAPI, model) {
63
60
  }
64
61
  if (!model.activeState) throw Error('no activestate');
65
62
  const worldCoords = currentWorldCoords(e);
66
- if (worldCoords) {
67
- model.activeState.setOrigin(worldCoords);
68
- model.previousPosition = worldCoords;
69
- }
63
+ model.activeState.setOrigin(worldCoords);
70
64
  return macro.VOID;
71
65
  };
72
66
  publicAPI.grabFocus = () => {
@@ -295,7 +295,8 @@ function widgetBehavior(publicAPI, model) {
295
295
  model.shapeHandle.setDirection(normal);
296
296
  }
297
297
  const {
298
- worldCoords
298
+ worldCoords,
299
+ worldDelta
299
300
  } = manipulator.handleEvent(callData, model._apiSpecificRenderWindow);
300
301
  if (!worldCoords.length) {
301
302
  return macro.VOID;
@@ -311,11 +312,11 @@ function widgetBehavior(publicAPI, model) {
311
312
  }
312
313
  } else if (model._isDragging) {
313
314
  if (model.activeState === model.point1Handle) {
314
- model.point1Handle.setOrigin(worldCoords);
315
- model.point1 = worldCoords;
315
+ vtkMath.add(model.point1Handle.getOrigin(), worldDelta, model.point1);
316
+ model.point1Handle.setOrigin(model.point1);
316
317
  } else {
317
- model.point2Handle.setOrigin(worldCoords);
318
- model.point2 = worldCoords;
318
+ vtkMath.add(model.point2Handle.getOrigin(), worldDelta, model.point2);
319
+ model.point2Handle.setOrigin(model.point2);
319
320
  }
320
321
  publicAPI.updateShapeBounds();
321
322
  publicAPI.invokeInteractionEvent();
@@ -332,10 +333,10 @@ function widgetBehavior(publicAPI, model) {
332
333
  if (!model.activeState || !model.activeState.getActive() || !model.pickable || !manipulator) {
333
334
  return macro.VOID;
334
335
  }
336
+ const {
337
+ worldCoords
338
+ } = manipulator.handleEvent(e, model._apiSpecificRenderWindow);
335
339
  if (model.hasFocus) {
336
- const {
337
- worldCoords
338
- } = manipulator.handleEvent(e, model._apiSpecificRenderWindow);
339
340
  if (!model.point1) {
340
341
  model.point1Handle.setOrigin(worldCoords);
341
342
  publicAPI.placePoint1(model.point1Handle.getOrigin());
@@ -1,4 +1,5 @@
1
1
  import { m as macro } from '../../../macros2.js';
2
+ import { k as add } from '../../../Common/Core/Math/index.js';
2
3
  import { vec3 } from 'gl-matrix';
3
4
 
4
5
  function widgetBehavior(publicAPI, model) {
@@ -10,8 +11,6 @@ function widgetBehavior(publicAPI, model) {
10
11
 
11
12
  // Set while moving the center or border handle.
12
13
  model._isDragging = false;
13
- // The last world coordinate of the mouse cursor during dragging.
14
- model.previousPosition = null;
15
14
  model.classHierarchy.push('vtkSphereWidgetProp');
16
15
  moveHandle.setVisible(true);
17
16
  centerHandle.setVisible(false);
@@ -47,7 +46,7 @@ function widgetBehavior(publicAPI, model) {
47
46
  }
48
47
  function currentWorldCoords(e) {
49
48
  const manipulator = model.activeState?.getManipulator?.() ?? model.manipulator;
50
- return manipulator.handleEvent(e, model._apiSpecificRenderWindow).worldCoords;
49
+ return manipulator.handleEvent(e, model._apiSpecificRenderWindow);
51
50
  }
52
51
 
53
52
  // Update the sphere's center and radius. Example:
@@ -75,19 +74,22 @@ function widgetBehavior(publicAPI, model) {
75
74
  model.activeState = null;
76
75
  return macro.VOID;
77
76
  }
78
- const worldCoords = currentWorldCoords(e);
77
+ const {
78
+ worldCoords
79
+ } = currentWorldCoords(e);
79
80
  if (model.activeState === moveHandle) {
80
81
  // Initial sphere placement.
81
82
  if (!centerHandle.getOrigin()) {
82
83
  centerHandle.setOrigin(worldCoords);
83
84
  } else if (!borderHandle.getOrigin()) {
84
85
  borderHandle.setOrigin(worldCoords);
86
+ publicAPI.loseFocus();
85
87
  }
86
88
  updateSphere();
89
+ return macro.EVENT_ABORT;
87
90
  }
88
91
  model._isDragging = true;
89
92
  model._apiSpecificRenderWindow.setCursor('grabbing');
90
- model.previousPosition = [...currentWorldCoords(e)];
91
93
  publicAPI.invokeStartInteractionEvent();
92
94
  return macro.EVENT_ABORT;
93
95
  };
@@ -97,7 +99,6 @@ function widgetBehavior(publicAPI, model) {
97
99
  return macro.VOID;
98
100
  }
99
101
  if (isPlaced()) {
100
- model.previousPosition = null;
101
102
  model._widgetManager.enablePicking();
102
103
  model._apiSpecificRenderWindow.setCursor('pointer');
103
104
  model._isDragging = false;
@@ -108,43 +109,33 @@ function widgetBehavior(publicAPI, model) {
108
109
  return macro.EVENT_ABORT;
109
110
  };
110
111
  publicAPI.handleMouseMove = e => {
111
- if (!model._isDragging) {
112
- model.activeState = null;
113
- return macro.VOID;
112
+ if (!model.activeState) return macro.VOID;
113
+ const {
114
+ worldCoords,
115
+ worldDelta
116
+ } = currentWorldCoords(e);
117
+ if (model.hasFocus) {
118
+ model.activeState.setOrigin(worldCoords);
119
+ } else if (model._isDragging) {
120
+ model.activeState.setOrigin(add(model.activeState.getOrigin(), worldDelta, []));
114
121
  }
115
- if (!model.activeState) throw Error('no activestate');
116
- const worldCoords = currentWorldCoords(e);
117
- model.activeState.setOrigin(worldCoords);
118
- if (model.activeState === centerHandle) {
119
- // When the sphere is fully placed, and the user is moving the
120
- // center, we move the whole sphere.
121
- if (borderHandle.getOrigin()) {
122
- if (!model.previousPosition) {
123
- // !previousPosition here happens only immediately
124
- // after grabFocus, but grabFocus resets
125
- // borderHandle.origin.
126
- throw Error(`no pos ${model.activeState} ${model.previousPosition}`);
127
- }
128
- const translation = vec3.sub(vec3.create(), worldCoords, model.previousPosition);
129
- borderHandle.setOrigin(vec3.add(vec3.create(), borderHandle.getOrigin(), translation));
130
- }
131
- }
132
- model.previousPosition = worldCoords;
133
122
  updateSphere();
134
123
  return macro.VOID;
135
124
  };
125
+ const superGrabFocus = publicAPI.grabFocus;
136
126
  publicAPI.grabFocus = () => {
127
+ superGrabFocus();
137
128
  moveHandle.setVisible(true);
138
129
  centerHandle.setVisible(false);
139
130
  borderHandle.setVisible(false);
140
131
  centerHandle.setOrigin(null);
141
132
  borderHandle.setOrigin(null);
142
- model._isDragging = true;
143
133
  model.activeState = moveHandle;
144
134
  model._interactor.render();
145
135
  };
136
+ const superLoseFocus = publicAPI.loseFocus;
146
137
  publicAPI.loseFocus = () => {
147
- model._isDragging = false;
138
+ superLoseFocus();
148
139
  model.activeState = null;
149
140
  };
150
141
  }
@@ -1,4 +1,5 @@
1
1
  import { m as macro } from '../../../macros2.js';
2
+ import { k as add } from '../../../Common/Core/Math/index.js';
2
3
  import { vec3 } from 'gl-matrix';
3
4
 
4
5
  function widgetBehavior(publicAPI, model) {
@@ -153,9 +154,13 @@ function widgetBehavior(publicAPI, model) {
153
154
  // --------------------------------------------------------------------------
154
155
 
155
156
  publicAPI.handleLeftButtonPress = e => {
156
- if (!model.activeState || !model.activeState.getActive() || !model.pickable) {
157
+ const manipulator = model.activeState?.getManipulator?.() ?? model.manipulator;
158
+ if (!manipulator || !model.activeState || !model.activeState.getActive() || !model.pickable) {
157
159
  return macro.VOID;
158
160
  }
161
+
162
+ // update worldDelta
163
+ manipulator.handleEvent(e, model._apiSpecificRenderWindow);
159
164
  if (model.activeState === model.moveHandle) {
160
165
  if (model.widgetState.getHandleList().length === 0) {
161
166
  addPoint();
@@ -230,7 +235,8 @@ function widgetBehavior(publicAPI, model) {
230
235
  return macro.VOID;
231
236
  }
232
237
  const {
233
- worldCoords
238
+ worldCoords,
239
+ worldDelta
234
240
  } = manipulator.handleEvent(callData, model._apiSpecificRenderWindow);
235
241
  const hoveredHandle = getHoveredHandle();
236
242
  if (hoveredHandle) {
@@ -245,8 +251,14 @@ function widgetBehavior(publicAPI, model) {
245
251
  if (model.lastHandle) {
246
252
  model.lastHandle.setVisible(true);
247
253
  }
248
- if (worldCoords.length && (model._isDragging || model.activeState === model.moveHandle)) {
249
- model.activeState.setOrigin(worldCoords);
254
+ const isHandleMoving = model._isDragging || model.activeState === model.moveHandle;
255
+ if (worldCoords.length && isHandleMoving) {
256
+ const curOrigin = model.activeState.getOrigin();
257
+ if (curOrigin) {
258
+ model.activeState.setOrigin(add(curOrigin, worldDelta, []));
259
+ } else {
260
+ model.activeState.setOrigin(worldCoords);
261
+ }
250
262
  if (model._isDragging) {
251
263
  model.draggedPoint = true;
252
264
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitware/vtk.js",
3
- "version": "30.5.2",
3
+ "version": "30.6.0",
4
4
  "description": "Visualization Toolkit for the Web",
5
5
  "keywords": [
6
6
  "3d",