@kitware/vtk.js 33.0.0-beta.3 → 33.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/BREAKING_CHANGES.md +0 -3
  2. package/Common/Core/DataArray.d.ts +17 -0
  3. package/Common/Core/DataArray.js +36 -0
  4. package/Common/Core/ScalarsToColors/Constants.js +7 -2
  5. package/Common/Core/ScalarsToColors.js +3 -1
  6. package/Rendering/Core/AbstractImageMapper.d.ts +81 -0
  7. package/Rendering/Core/AbstractImageMapper.js +5 -2
  8. package/Rendering/Core/AbstractPicker.d.ts +13 -13
  9. package/Rendering/Core/AbstractPicker.js +1 -1
  10. package/Rendering/Core/Actor.d.ts +20 -5
  11. package/Rendering/Core/Actor.js +68 -5
  12. package/Rendering/Core/Actor2D.d.ts +22 -0
  13. package/Rendering/Core/Actor2D.js +1 -1
  14. package/Rendering/Core/CellPicker.js +4 -1
  15. package/Rendering/Core/ColorTransferFunction.js +26 -35
  16. package/Rendering/Core/ImageCPRMapper.d.ts +20 -1
  17. package/Rendering/Core/ImageCPRMapper.js +7 -5
  18. package/Rendering/Core/ImageResliceMapper.d.ts +20 -2
  19. package/Rendering/Core/ImageResliceMapper.js +7 -5
  20. package/Rendering/Core/ImageSlice.d.ts +23 -7
  21. package/Rendering/Core/ImageSlice.js +68 -9
  22. package/Rendering/Core/Mapper.js +8 -16
  23. package/Rendering/Core/Prop3D.d.ts +2 -39
  24. package/Rendering/Core/Prop3D.js +2 -81
  25. package/Rendering/Core/ScalarBarActor.js +4 -2
  26. package/Rendering/Core/Viewport.js +13 -3
  27. package/Rendering/Core/Volume.d.ts +20 -5
  28. package/Rendering/Core/Volume.js +70 -2
  29. package/Rendering/Core/VolumeMapper/Constants.d.ts +7 -0
  30. package/Rendering/Core/VolumeMapper/Constants.js +8 -2
  31. package/Rendering/Core/VolumeMapper.d.ts +243 -16
  32. package/Rendering/Core/VolumeMapper.js +60 -20
  33. package/Rendering/Core/VolumeProperty/Constants.d.ts +3 -12
  34. package/Rendering/Core/VolumeProperty/Constants.js +4 -11
  35. package/Rendering/Core/VolumeProperty.d.ts +4 -120
  36. package/Rendering/Core/VolumeProperty.js +4 -49
  37. package/Rendering/Misc/SynchronizableRenderWindow/BehaviorManager/CameraSynchronizer.js +2 -2
  38. package/Rendering/OpenGL/ImageCPRMapper.js +36 -29
  39. package/Rendering/OpenGL/ImageMapper.js +55 -31
  40. package/Rendering/OpenGL/ImageResliceMapper.js +191 -263
  41. package/Rendering/OpenGL/PolyDataMapper.js +8 -1
  42. package/Rendering/OpenGL/RenderWindow/resourceSharingHelper.d.ts +3 -3
  43. package/Rendering/OpenGL/RenderWindow/resourceSharingHelper.js +5 -8
  44. package/Rendering/OpenGL/Renderer.js +1 -1
  45. package/Rendering/OpenGL/Texture.d.ts +29 -8
  46. package/Rendering/OpenGL/Texture.js +154 -23
  47. package/Rendering/OpenGL/VolumeMapper.js +792 -712
  48. package/Rendering/OpenGL/glsl/vtkVolumeFS.glsl.js +1 -1
  49. package/Rendering/SceneGraph/ViewNode.js +12 -2
  50. package/Rendering/WebGPU/VolumePassFSQ.js +2 -2
  51. package/Rendering/WebXR/RenderWindowHelper.js +9 -0
  52. package/Widgets/Core/WidgetManager.d.ts +12 -1
  53. package/Widgets/Representations/WidgetRepresentation.d.ts +1 -7
  54. package/Widgets/Widgets3D/ResliceCursorWidget.d.ts +1 -8
  55. package/index.d.ts +0 -1
  56. package/macros2.js +1 -1
  57. package/package.json +11 -11
  58. package/Interaction/Manipulators/KeyboardCameraManipulator.d.ts +0 -113
@@ -1,5 +1,5 @@
1
1
  import { mat3, mat4, quat, vec3 } from 'gl-matrix';
2
- import { Nullable } from './../../types';
2
+ import { Extent, Nullable } from './../../types';
3
3
  import { vtkOutputPort } from './../../interfaces';
4
4
  import vtkAbstractMapper3D, {
5
5
  IAbstractMapper3DInitialValues,
@@ -307,6 +307,25 @@ export interface vtkImageCPRMapper
307
307
  * @param imageData
308
308
  */
309
309
  setImageConnection(imageData: vtkOutputPort): void;
310
+
311
+ /**
312
+ * Tells the mapper to only update the specified extents.
313
+ *
314
+ * If there are zero extents, the mapper updates the entire volume texture.
315
+ * Otherwise, the mapper will only update the texture by the specified extents
316
+ * during the next render call.
317
+ *
318
+ * This array is cleared after a successful render.
319
+ * @param extents
320
+ */
321
+ setUpdatedExtents(extents: Extent[]): boolean;
322
+
323
+ /**
324
+ * Retrieves the updated extents.
325
+ *
326
+ * This array is cleared after every successful render.
327
+ */
328
+ getUpdatedExtents(): Extent[];
310
329
  }
311
330
 
312
331
  /**
@@ -270,7 +270,7 @@ function vtkImageCPRMapper(publicAPI, model) {
270
270
  // Object factory
271
271
  // ----------------------------------------------------------------------------
272
272
 
273
- const DEFAULT_VALUES = {
273
+ const defaultValues = initialValues => ({
274
274
  width: 10,
275
275
  uniformOrientation: [0, 0, 0, 1],
276
276
  useUniformOrientation: false,
@@ -282,14 +282,16 @@ const DEFAULT_VALUES = {
282
282
  normalDirection: [0, 0, 1],
283
283
  projectionSlabThickness: 1,
284
284
  projectionSlabNumberOfSamples: 1,
285
- projectionMode: ProjectionMode.MAX
286
- };
285
+ projectionMode: ProjectionMode.MAX,
286
+ updatedExtents: [],
287
+ ...initialValues
288
+ });
287
289
 
288
290
  // ----------------------------------------------------------------------------
289
291
 
290
292
  function extend(publicAPI, model) {
291
293
  let initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
292
- Object.assign(model, DEFAULT_VALUES, initialValues);
294
+ Object.assign(model, defaultValues(initialValues));
293
295
 
294
296
  // Inheritance
295
297
  vtkAbstractImageMapper.extend(publicAPI, model, initialValues);
@@ -302,7 +304,7 @@ function extend(publicAPI, model) {
302
304
  });
303
305
 
304
306
  // Setters and getters
305
- macro.setGet(publicAPI, model, ['width', 'uniformOrientation', 'useUniformOrientation', 'centerPoint', 'preferSizeOverAccuracy', 'orientationArrayName', 'tangentDirection', 'bitangentDirection', 'normalDirection', 'projectionSlabThickness', 'projectionSlabNumberOfSamples', 'projectionMode']);
307
+ macro.setGet(publicAPI, model, ['width', 'uniformOrientation', 'useUniformOrientation', 'centerPoint', 'preferSizeOverAccuracy', 'orientationArrayName', 'tangentDirection', 'bitangentDirection', 'normalDirection', 'projectionSlabThickness', 'projectionSlabNumberOfSamples', 'projectionMode', 'updatedExtents']);
306
308
  CoincidentTopologyHelper.implementCoincidentTopologyMethods(publicAPI, model);
307
309
 
308
310
  // Object methods
@@ -1,10 +1,9 @@
1
1
  import vtkAbstractImageMapper, {
2
2
  IAbstractImageMapperInitialValues,
3
3
  } from './AbstractImageMapper';
4
- import vtkImageData from './../../Common/DataModel/ImageData';
5
4
  import vtkPlane from './../../Common/DataModel/Plane';
6
5
  import vtkPolyData from './../../Common/DataModel/PolyData';
7
- import { Bounds, Nullable, Vector3 } from './../../types';
6
+ import { Bounds, Extent } from './../../types';
8
7
  import { SlabTypes } from './ImageResliceMapper/Constants';
9
8
  import CoincidentTopologyHelper, {
10
9
  StaticCoincidentTopologyMethods,
@@ -116,6 +115,25 @@ export interface vtkImageResliceMapper
116
115
  * @param {vtkPolyData} slicePolyData The polydata to slice the volume with. Default: null
117
116
  */
118
117
  setSlicePolyData(slicePolyData: vtkPolyData): boolean;
118
+
119
+ /**
120
+ * Tells the mapper to only update the specified extents.
121
+ *
122
+ * If there are zero extents, the mapper updates the entire volume texture.
123
+ * Otherwise, the mapper will only update the texture by the specified extents
124
+ * during the next render call.
125
+ *
126
+ * This array is cleared after a successful render.
127
+ * @param extents
128
+ */
129
+ setUpdatedExtents(extents: Extent[]): boolean;
130
+
131
+ /**
132
+ * Retrieves the updated extents.
133
+ *
134
+ * This array is cleared after every successful render.
135
+ */
136
+ getUpdatedExtents(): Extent[];
119
137
  }
120
138
 
121
139
  /**
@@ -38,23 +38,25 @@ function vtkImageResliceMapper(publicAPI, model) {
38
38
  // Object factory
39
39
  // ----------------------------------------------------------------------------
40
40
 
41
- const DEFAULT_VALUES = {
41
+ const defaultValues = initialValues => ({
42
42
  slabThickness: 0.0,
43
43
  slabTrapezoidIntegration: 0,
44
44
  slabType: SlabTypes.MEAN,
45
45
  slicePlane: null,
46
- slicePolyData: null
47
- };
46
+ slicePolyData: null,
47
+ updatedExtents: [],
48
+ ...initialValues
49
+ });
48
50
 
49
51
  // ----------------------------------------------------------------------------
50
52
 
51
53
  function extend(publicAPI, model) {
52
54
  let initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
53
- Object.assign(model, DEFAULT_VALUES, initialValues);
55
+ Object.assign(model, defaultValues(initialValues));
54
56
 
55
57
  // Build VTK API
56
58
  vtkAbstractImageMapper.extend(publicAPI, model, initialValues);
57
- macro.setGet(publicAPI, model, ['slabThickness', 'slabTrapezoidIntegration', 'slabType', 'slicePlane', 'slicePolyData']);
59
+ macro.setGet(publicAPI, model, ['slabThickness', 'slabTrapezoidIntegration', 'slabType', 'slicePlane', 'slicePolyData', 'updatedExtents']);
58
60
  CoincidentTopologyHelper.implementCoincidentTopologyMethods(publicAPI, model);
59
61
 
60
62
  // Object methods
@@ -17,6 +17,18 @@ export interface vtkImageSlice extends vtkProp3D {
17
17
  */
18
18
  getActors(): any;
19
19
 
20
+ /**
21
+ * Get the bounds for this mapper as [xmin, xmax, ymin, ymax,zmin, zmax].
22
+ * @return {Bounds} The bounds for the mapper.
23
+ */
24
+ getBounds(): Bounds;
25
+
26
+ /**
27
+ * Get the bounds for this mapper as [xmin, xmax, ymin, ymax,zmin, zmax].
28
+ * @return {Bounds} The bounds for the mapper.
29
+ */
30
+ getBoundsByReference(): Bounds;
31
+
20
32
  /**
21
33
  * Get the bounds for a given slice as [xmin, xmax, ymin, ymax,zmin, zmax].
22
34
  * @param {Number} slice The slice index. If undefined, the current slice is considered.
@@ -35,6 +47,11 @@ export interface vtkImageSlice extends vtkProp3D {
35
47
  */
36
48
  getIsOpaque(): boolean;
37
49
 
50
+ /**
51
+ *
52
+ */
53
+ getProperty(): vtkImageProperty;
54
+
38
55
  /**
39
56
  *
40
57
  */
@@ -113,6 +130,12 @@ export interface vtkImageSlice extends vtkProp3D {
113
130
  */
114
131
  setMapper(mapper: vtkAbstractImageMapper): boolean;
115
132
 
133
+ /**
134
+ *
135
+ * @param {vtkImageProperty} property The vtkImageProperty instance.
136
+ */
137
+ setProperty(property: vtkImageProperty): boolean;
138
+
116
139
  /**
117
140
  *
118
141
  * @param {boolean} forceOpaque If true, render during opaque pass even if opacity value is below 1.0.
@@ -124,13 +147,6 @@ export interface vtkImageSlice extends vtkProp3D {
124
147
  * @param {boolean} forceTranslucent If true, render during translucent pass even if opacity value is 1.0.
125
148
  */
126
149
  setForceTranslucent(forceTranslucent: boolean): boolean;
127
-
128
- // Inherited from vtkProp3D, but takes a vtkImageProperty instead of a generic vtkObject
129
- getProperty(mapperInputPort?: number): vtkImageProperty;
130
- getProperties(): vtkImageProperty[];
131
- setProperty(mapperInputPort: number, property: vtkImageProperty): boolean;
132
- setProperty(property: vtkImageProperty): boolean;
133
- setProperties(properties: vtkImageProperty[]): boolean;
134
150
  }
135
151
 
136
152
  /**
@@ -4,6 +4,10 @@ import vtkBoundingBox from '../../Common/DataModel/BoundingBox.js';
4
4
  import vtkProp3D from './Prop3D.js';
5
5
  import vtkImageProperty from './ImageProperty.js';
6
6
 
7
+ const {
8
+ vtkDebugMacro
9
+ } = macro;
10
+
7
11
  // ----------------------------------------------------------------------------
8
12
  // vtkImageSlice methods
9
13
  // ----------------------------------------------------------------------------
@@ -21,11 +25,11 @@ function vtkImageSlice(publicAPI, model) {
21
25
  return false;
22
26
  }
23
27
  // make sure we have a property
24
- if (!model.properties[0]) {
28
+ if (!model.property) {
25
29
  // force creation of a property
26
30
  publicAPI.getProperty();
27
31
  }
28
- let isOpaque = model.properties[0].getOpacity() >= 1.0;
32
+ let isOpaque = model.property.getOpacity() >= 1.0;
29
33
 
30
34
  // are we using an opaque scalar array, if any?
31
35
  isOpaque = isOpaque && (!model.mapper || model.mapper.getIsOpaque());
@@ -39,6 +43,48 @@ function vtkImageSlice(publicAPI, model) {
39
43
  // and the Renderer will do the images in their own pass.
40
44
  publicAPI.hasTranslucentPolygonalGeometry = () => false;
41
45
  publicAPI.makeProperty = vtkImageProperty.newInstance;
46
+ publicAPI.getProperty = () => {
47
+ if (model.property === null) {
48
+ model.property = publicAPI.makeProperty();
49
+ }
50
+ return model.property;
51
+ };
52
+ publicAPI.getBounds = () => {
53
+ if (model.mapper === null) {
54
+ return model.bounds;
55
+ }
56
+
57
+ // Check for the special case when the mapper's bounds are unknown
58
+ const bds = model.mapper.getBounds();
59
+ if (!bds || bds.length !== 6) {
60
+ return bds;
61
+ }
62
+
63
+ // Check for the special case when the actor is empty.
64
+ if (bds[0] > bds[1]) {
65
+ model.mapperBounds = bds.concat(); // copy the mapper's bounds
66
+ model.bounds = [1, -1, 1, -1, 1, -1];
67
+ model.boundsMTime.modified();
68
+ return bds;
69
+ }
70
+
71
+ // Check if we have cached values for these bounds - we cache the
72
+ // values returned by model.mapper.getBounds() and we store the time
73
+ // of caching. If the values returned this time are different, or
74
+ // the modified time of this class is newer than the cached time,
75
+ // then we need to rebuild.
76
+ const zip = rows => rows[0].map((_, c) => rows.map(row => row[c]));
77
+ if (!model.mapperBounds || !zip([bds, model.mapperBounds]).reduce((a, b) => a && b[0] === b[1], true) || publicAPI.getMTime() > model.boundsMTime.getMTime()) {
78
+ vtkDebugMacro('Recomputing bounds...');
79
+ model.mapperBounds = bds.map(x => x);
80
+ publicAPI.computeMatrix();
81
+ const tmp4 = new Float64Array(16);
82
+ mat4.transpose(tmp4, model.matrix);
83
+ vtkBoundingBox.transformBounds(bds, tmp4, model.bounds);
84
+ model.boundsMTime.modified();
85
+ }
86
+ return model.bounds;
87
+ };
42
88
  publicAPI.getBoundsForSlice = (slice, thickness) => {
43
89
  // Check for the special case when the mapper's bounds are unknown
44
90
  const bds = model.mapper.getBoundsForSlice(slice, thickness);
@@ -71,6 +117,14 @@ function vtkImageSlice(publicAPI, model) {
71
117
 
72
118
  // Get the maximum Z bound
73
119
  publicAPI.getMaxZBound = () => publicAPI.getBounds()[5];
120
+ publicAPI.getMTime = () => {
121
+ let mt = model.mtime;
122
+ if (model.property !== null) {
123
+ const time = model.property.getMTime();
124
+ mt = time > mt ? time : mt;
125
+ }
126
+ return mt;
127
+ };
74
128
  publicAPI.getRedrawMTime = () => {
75
129
  let mt = model.mtime;
76
130
  if (model.mapper !== null) {
@@ -83,13 +137,14 @@ function vtkImageSlice(publicAPI, model) {
83
137
  mt = time > mt ? time : mt;
84
138
  }
85
139
  }
86
- model.properties.forEach(property => {
87
- mt = Math.max(mt, property.getMTime());
88
- const rgbFunc = property.getRGBTransferFunction();
89
- if (rgbFunc !== null) {
90
- mt = Math.max(mt, rgbFunc.getMTime());
140
+ if (model.property !== null) {
141
+ let time = model.property.getMTime();
142
+ mt = time > mt ? time : mt;
143
+ if (model.property.getRGBTransferFunction() !== null) {
144
+ time = model.property.getRGBTransferFunction().getMTime();
145
+ mt = time > mt ? time : mt;
91
146
  }
92
- });
147
+ }
93
148
  return mt;
94
149
  };
95
150
  publicAPI.getSupportsSelection = () => model.mapper ? model.mapper.getSupportsSelection() : false;
@@ -101,8 +156,10 @@ function vtkImageSlice(publicAPI, model) {
101
156
 
102
157
  const DEFAULT_VALUES = {
103
158
  mapper: null,
159
+ property: null,
104
160
  forceOpaque: false,
105
- forceTranslucent: false
161
+ forceTranslucent: false,
162
+ bounds: [...vtkBoundingBox.INIT_BOUNDS]
106
163
  };
107
164
 
108
165
  // ----------------------------------------------------------------------------
@@ -119,7 +176,9 @@ function extend(publicAPI, model) {
119
176
  macro.obj(model.boundsMTime);
120
177
 
121
178
  // Build VTK API
179
+ macro.set(publicAPI, model, ['property']);
122
180
  macro.setGet(publicAPI, model, ['mapper', 'forceOpaque', 'forceTranslucent']);
181
+ macro.getArray(publicAPI, model, ['bounds'], 6);
123
182
 
124
183
  // Object methods
125
184
  vtkImageSlice(publicAPI, model);
@@ -137,11 +137,10 @@ const colorTextureCoordinatesCache = new WeakMap();
137
137
  * @param {Range} range The range of the scalars
138
138
  * @param {Number} numberOfColorsInRange The number of colors that are used in the range
139
139
  * @param {vec3} dimensions The dimensions of the texture
140
- * @param {boolean} useLogScale If log scale should be used to transform input scalars
141
140
  * @param {boolean} useZigzagPattern If a zigzag pattern should be used. Otherwise 1 row for colors (including min and max) and 1 row for NaN are used.
142
141
  * @returns A vtkDataArray containing the texture coordinates (2D or 3D)
143
142
  */
144
- function getOrCreateColorTextureCoordinates(input, component, range, numberOfColorsInRange, dimensions, useLogScale, useZigzagPattern) {
143
+ function getOrCreateColorTextureCoordinates(input, component, range, numberOfColorsInRange, dimensions, useZigzagPattern) {
145
144
  // Caching using the "arguments" special object (because it is a pure function)
146
145
  const argStrings = new Array(arguments.length);
147
146
  for (let argIndex = 0; argIndex < arguments.length; ++argIndex) {
@@ -202,11 +201,6 @@ function getOrCreateColorTextureCoordinates(input, component, range, numberOfCol
202
201
  }
203
202
  inputIdx += numComps;
204
203
 
205
- // Apply log scale if necessary
206
- if (useLogScale) {
207
- scalarValue = vtkLookupTable.applyLogScale(scalarValue, range, range);
208
- }
209
-
210
204
  // Convert to texture coordinates and update output
211
205
  if (isNan(scalarValue)) {
212
206
  // Last texels are NaN colors (there is at least one NaN color)
@@ -401,10 +395,6 @@ function vtkMapper(publicAPI, model) {
401
395
  model.mapScalarsToTexture = (scalars, cellFlag, alpha) => {
402
396
  const range = model.lookupTable.getRange();
403
397
  const useLogScale = model.lookupTable.usingLogScale();
404
- if (useLogScale) {
405
- // convert range to log.
406
- vtkLookupTable.getLogRange(range, range);
407
- }
408
398
  const origAlpha = model.lookupTable.getAlpha();
409
399
 
410
400
  // Get rid of vertex color array. Only texture or vertex coloring
@@ -448,14 +438,16 @@ function vtkMapper(publicAPI, model) {
448
438
  const numberOfNonSpecialColors = model.numberOfColorsInRange;
449
439
  const numberOfNonNaNColors = numberOfNonSpecialColors + 2;
450
440
  const textureCoordinates = [0, 0, 0];
451
- const rangeMin = range[0];
452
- const rangeDifference = range[1] - range[0];
441
+ const scaledRange = useLogScale ? [Math.log10(range[0]), Math.log10(range[1])] : range;
442
+ const rangeMin = scaledRange[0];
443
+ const rangeDifference = scaledRange[1] - scaledRange[0];
453
444
  for (let i = 0; i < numberOfNonNaNColors; ++i) {
454
445
  const scalarsArrayIndex = getIndexFromCoordinates(textureCoordinates, textureDimensions);
455
446
 
456
447
  // Minus 1 start at min color
457
- const scalarValue = rangeMin + rangeDifference * (i - 1) / (numberOfNonSpecialColors - 1);
458
- scalarsArray[scalarsArrayIndex] = useLogScale ? 10.0 ** scalarValue : scalarValue;
448
+ const intermediateValue = rangeMin + rangeDifference * (i - 1) / (numberOfNonSpecialColors - 1);
449
+ const scalarValue = useLogScale ? 10.0 ** intermediateValue : intermediateValue;
450
+ scalarsArray[scalarsArrayIndex] = scalarValue;
459
451
 
460
452
  // Colors are zigzagging to allow interpolation between two neighbor colors when coloring cells
461
453
  updateZigzaggingCoordinates(textureCoordinates, textureDimensions);
@@ -480,7 +472,7 @@ function vtkMapper(publicAPI, model) {
480
472
  // A zigzag pattern can be used with cell data, as there will be no texture coordinates interpolation
481
473
  // The texture generated using a zigzag pattern in one dimension is the same as without zigzag
482
474
  // Therefore, the same code can be used for texture generation of point/cell data but not for texture coordinates
483
- model.colorCoordinates = getOrCreateColorTextureCoordinates(scalars, scalarComponent, range, model.numberOfColorsInRange, model.colorTextureMap.getDimensions(), useLogScale, cellFlag);
475
+ model.colorCoordinates = getOrCreateColorTextureCoordinates(scalars, scalarComponent, range, model.numberOfColorsInRange, model.colorTextureMap.getDimensions(), cellFlag);
484
476
  };
485
477
  publicAPI.getIsOpaque = () => {
486
478
  const input = publicAPI.getInputData();
@@ -1,7 +1,6 @@
1
1
  import { mat4, quat } from 'gl-matrix';
2
2
  import { Bounds, Vector3, Range } from './../../types';
3
3
  import vtkProp, { IPropInitialValues } from './Prop';
4
- import { vtkObject } from './../../interfaces';
5
4
 
6
5
  export interface IProp3DInitialValues extends IPropInitialValues {
7
6
  origin?: number[];
@@ -20,17 +19,11 @@ export interface vtkProp3D extends vtkProp {
20
19
  addPosition(deltaXYZ: number[]): void;
21
20
 
22
21
  /**
23
- * Get the bounds of this actor as [xmin, xmax, ymin, ymax, zmin, zmax].
24
- * They are the bounds of the underlying mapper, transformed using the actor's matrix.
25
- * @return {Bounds} The bounds for the actor.
22
+ * Get the bounds as [xmin, xmax, ymin, ymax, zmin, zmax].
23
+ * @return {Bounds} The bounds for the mapper.
26
24
  */
27
25
  getBounds(): Bounds;
28
26
 
29
- /**
30
- * Same as getBounds() but the returned array is not copied, so it should not be written to.
31
- */
32
- getBoundsByReference(): Bounds;
33
-
34
27
  /**
35
28
  * Check if there was a modification or transformation.
36
29
  * @default null
@@ -138,21 +131,6 @@ export interface vtkProp3D extends vtkProp {
138
131
  */
139
132
  getUserMatrix(): mat4;
140
133
 
141
- /**
142
- * Get the actor property for the specified mapper input port, which defaults to 0
143
- * It controls this actors rendering properties. If one isn’t specified,
144
- * then one will be generated automatically. Multiple actors can share one
145
- * property object.
146
- * @param {number} mapperInputPort Defaults to 0
147
- */
148
- getProperty(mapperInputPort?: number): vtkObject;
149
-
150
- /**
151
- * Get the actor properties array
152
- * Each element of the array corresponds to a mapper input port
153
- */
154
- getProperties(): vtkObject[];
155
-
156
134
  /**
157
135
  * Rotate the Prop3D in degrees about the X axis using the right hand
158
136
  * rule. The axis is the Prop3D’s X axis, which can change as other
@@ -278,21 +256,6 @@ export interface vtkProp3D extends vtkProp {
278
256
  * Generate the matrix based on internal model.
279
257
  */
280
258
  computeMatrix(): void;
281
-
282
- /**
283
- * Set the actor property for the specified mapper input port, which defaults to 0
284
- * @param {vtkObject} property
285
- * @param {number} mapperInputPort Is 0 when not given
286
- */
287
- setProperty(mapperInputPort: number, property: vtkObject): boolean;
288
- setProperty(property: vtkObject): boolean;
289
-
290
- /**
291
- * Set the actor properties array
292
- * Each element of the array corresponds to a mapper input port
293
- * @param {vtkObject[]} properties
294
- */
295
- setProperties(properties: vtkObject[]): boolean;
296
259
  }
297
260
 
298
261
  /**
@@ -121,54 +121,6 @@ function vtkProp3D(publicAPI, model) {
121
121
  model.matrixMTime.modified();
122
122
  }
123
123
  };
124
- publicAPI.getBoundsByReference = () => {
125
- if (model.mapper === null) {
126
- return model.bounds;
127
- }
128
-
129
- // Check for the special case when the mapper's bounds are unknown
130
- const bds = model.mapper.getBounds();
131
- if (!bds || bds.length !== 6) {
132
- return bds;
133
- }
134
-
135
- // Check for the special case when the actor is empty.
136
- if (bds[0] > bds[1]) {
137
- // No need to copy bds, a new array is created when calling getBounds()
138
- model.mapperBounds = bds;
139
- model.bounds = [...vtkBoundingBox.INIT_BOUNDS];
140
- model.boundsMTime.modified();
141
- return bds;
142
- }
143
-
144
- // Check if we have cached values for these bounds - we cache the
145
- // values returned by model.mapper.getBounds() and we store the time
146
- // of caching. If the values returned this time are different, or
147
- // the modified time of this class is newer than the cached time,
148
- // then we need to rebuild.
149
- if (!model.mapperBounds || !bds.every((_, i) => bds[i] === model.mapperBounds[i]) || publicAPI.getMTime() > model.boundsMTime.getMTime()) {
150
- macro.vtkDebugMacro('Recomputing bounds...');
151
- // No need to copy bds, a new array is created when calling getBounds()
152
- model.mapperBounds = bds;
153
-
154
- // Compute actor bounds from matrix and mapper bounds
155
- publicAPI.computeMatrix();
156
- const transposedMatrix = new Float64Array(16);
157
- mat4.transpose(transposedMatrix, model.matrix);
158
- vtkBoundingBox.transformBounds(bds, transposedMatrix, model.bounds);
159
- model.boundsMTime.modified();
160
- }
161
- return model.bounds;
162
- };
163
- publicAPI.getBounds = () => {
164
- const bounds = publicAPI.getBoundsByReference();
165
- // Handle case when bounds are not iterable (for example null or undefined)
166
- try {
167
- return [...bounds];
168
- } catch {
169
- return bounds;
170
- }
171
- };
172
124
  publicAPI.getCenter = () => vtkBoundingBox.getCenter(model.bounds);
173
125
  publicAPI.getLength = () => vtkBoundingBox.getLength(model.bounds);
174
126
  publicAPI.getXRange = () => vtkBoundingBox.getXRange(model.bounds);
@@ -179,35 +131,6 @@ function vtkProp3D(publicAPI, model) {
179
131
  publicAPI.computeMatrix();
180
132
  }
181
133
  publicAPI.onModified(updateIdentityFlag);
182
- publicAPI.getProperty = function () {
183
- let mapperInputPort = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
184
- if (model.properties[mapperInputPort] == null) {
185
- model.properties[mapperInputPort] = publicAPI.makeProperty?.();
186
- }
187
- return model.properties[mapperInputPort];
188
- };
189
- publicAPI.setProperty = (firstArg, secondArg) => {
190
- // Two options for argument layout:
191
- // - (mapperInputPort, property)
192
- // - (property)
193
- const useInputPortArgument = Number.isInteger(firstArg);
194
- const [mapperInputPort, property] = useInputPortArgument ? [firstArg, secondArg] : [0, firstArg];
195
- if (model.properties[mapperInputPort] === property) {
196
- return false;
197
- }
198
- model.properties[mapperInputPort] = property;
199
- return true;
200
- };
201
- publicAPI.getMTime = () => {
202
- let mt = model.mtime;
203
- model.properties.forEach(property => {
204
- if (property !== null) {
205
- const time = property.getMTime();
206
- mt = time > mt ? time : mt;
207
- }
208
- });
209
- return mt;
210
- };
211
134
  }
212
135
 
213
136
  // ----------------------------------------------------------------------------
@@ -220,8 +143,7 @@ const DEFAULT_VALUES = {
220
143
  orientation: [0, 0, 0],
221
144
  rotation: null,
222
145
  scale: [1, 1, 1],
223
- bounds: [...vtkBoundingBox.INIT_BOUNDS],
224
- properties: [],
146
+ bounds: [1, -1, 1, -1, 1, -1],
225
147
  userMatrix: null,
226
148
  userMatrixMTime: null,
227
149
  cachedProp3D: null,
@@ -241,10 +163,9 @@ function extend(publicAPI, model) {
241
163
  macro.obj(model.matrixMTime);
242
164
 
243
165
  // Build VTK API
244
- macro.get(publicAPI, model, ['isIdentity']);
166
+ macro.get(publicAPI, model, ['bounds', 'isIdentity']);
245
167
  macro.getArray(publicAPI, model, ['orientation']);
246
168
  macro.setGetArray(publicAPI, model, ['origin', 'position', 'scale'], 3);
247
- macro.setGet(publicAPI, model, ['properties']);
248
169
 
249
170
  // Object internal instance
250
171
  model.matrix = mat4.identity(new Float64Array(16));
@@ -566,8 +566,10 @@ function vtkScalarBarActorHelper(publicAPI, model) {
566
566
  const tickSegmentSize = model.barSize[spacedAxis] * (tickSeg.corners[2][spacedAxis] - tickSeg.corners[0][spacedAxis]);
567
567
  const ticks = publicAPI.getTicks();
568
568
  const tickStrings = publicAPI.getTickStrings();
569
+ const tickPositions = publicAPI.getTickPositions();
569
570
  for (let t = 0; t < ticks.length; t++) {
570
- const tickPos = (ticks[t] - model.lastTickBounds[0]) / (model.lastTickBounds[1] - model.lastTickBounds[0]);
571
+ // If tickPositions is not set, use a normalized position
572
+ const tickPos = tickPositions ? tickPositions[t] : (ticks[t] - model.lastTickBounds[0]) / (model.lastTickBounds[1] - model.lastTickBounds[0]);
571
573
  tmpv3[spacedAxis] = tickSegmentStart + tickSegmentSize * tickPos;
572
574
  publicAPI.createPolyDataForOneLabel(tickStrings[t], tmpv3, alignment, 'horizontal', tickOffsets, results);
573
575
  }
@@ -651,7 +653,7 @@ const newScalarBarActorHelper = macro.newInstance(function (publicAPI, model) {
651
653
 
652
654
  // Inheritance
653
655
  macro.obj(publicAPI, model);
654
- macro.setGet(publicAPI, model, ['axisTitlePixelOffset', 'tickLabelPixelOffset', 'renderable', 'topTitle', 'ticks', 'tickStrings']);
656
+ macro.setGet(publicAPI, model, ['axisTitlePixelOffset', 'tickLabelPixelOffset', 'renderable', 'topTitle', 'ticks', 'tickStrings', 'tickPositions']);
655
657
  macro.get(publicAPI, model, ['lastSize', 'lastAspectRatio', 'lastTickBounds', 'axisTextStyle', 'tickTextStyle', 'barActor', 'tmActor']);
656
658
  macro.getArray(publicAPI, model, ['boxPosition', 'boxSize']);
657
659
  macro.setArray(publicAPI, model, ['boxPosition', 'boxSize'], 2);
@@ -46,10 +46,20 @@ function vtkViewport(publicAPI, model) {
46
46
  return allProps;
47
47
  }
48
48
  publicAPI.getViewPropsWithNestedProps = () => {
49
- const allPropsArray = [];
50
- for (let i = 0; i < model.props.length; i++) {
51
- gatherProps(model.props[i], allPropsArray);
49
+ let allPropsArray = [];
50
+ // Handle actor2D instances separately so that they can be overlayed and layered
51
+ const actors2D = publicAPI.getActors2D();
52
+ // Sort the actor2D list using its layer number
53
+ actors2D.sort((a, b) => a.getLayerNumber() - b.getLayerNumber());
54
+ // Filter out all the actor2D instances
55
+ const newPropList = model.props.filter(item => !actors2D.includes(item));
56
+ for (let i = 0; i < newPropList.length; i++) {
57
+ gatherProps(newPropList[i], allPropsArray);
52
58
  }
59
+ // Finally, add the actor2D props at the end of the list
60
+ // This works because, when traversing the render pass in vtkOpenGLRenderer, the children are
61
+ // traversed in the order that they are added to the list
62
+ allPropsArray = allPropsArray.concat(actors2D);
53
63
  return allPropsArray;
54
64
  };
55
65
  publicAPI.addActor2D = publicAPI.addViewProp;
@@ -29,6 +29,22 @@ export interface vtkVolume extends vtkProp3D {
29
29
  */
30
30
  getVolumes(): vtkVolume[];
31
31
 
32
+ /**
33
+ * Get the volume property
34
+ */
35
+ getProperty(): vtkVolumeProperty;
36
+
37
+ /**
38
+ * Get the bounds for this mapper as [xmin, xmax, ymin, ymax,zmin, zmax].
39
+ * @return {Bounds} The bounds for the mapper.
40
+ */
41
+ getBounds(): Bounds;
42
+
43
+ /**
44
+ * Get the bounds as [xmin, xmax, ymin, ymax, zmin, zmax].
45
+ */
46
+ getBoundsByReference(): Bounds;
47
+
32
48
  /**
33
49
  * Get the `Modified Time` which is a monotonic increasing integer
34
50
  * global for all vtkObjects.
@@ -59,12 +75,11 @@ export interface vtkVolume extends vtkProp3D {
59
75
  */
60
76
  setMapper(mapper: vtkVolumeMapper): boolean;
61
77
 
62
- // Inherited from vtkProp3D, but takes a vtkVolumeProperty instead of a generic vtkObject
63
- getProperty(mapperInputPort?: number): vtkVolumeProperty;
64
- getProperties(): vtkVolumeProperty[];
65
- setProperty(mapperInputPort: number, property: vtkVolumeProperty): boolean;
78
+ /**
79
+ * Set the volume property
80
+ * @param {vtkVolumeProperty} property
81
+ */
66
82
  setProperty(property: vtkVolumeProperty): boolean;
67
- setProperties(properties: vtkVolumeProperty[]): boolean;
68
83
  }
69
84
 
70
85
  /**