@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,6 +1,3 @@
1
- ## From 32.x to 33
2
-
3
- - **vtkMapper**: many properties have moved to `vtkVolumeProperty`. The full list of changed methods is: `getAnisotropy`, `getComputeNormalFromOpacity`, `getFilterMode`, `getFilterModeAsString`, `getGlobalIlluminationReach`, `getIpScalarRange`, `getIpScalarRangeByReference`, `getLAOKernelRadius`, `getLAOKernelSize`, `getLocalAmbientOcclusion`, `getPreferSizeOverAccuracy`, `getVolumetricScatteringBlending`, `setAnisotropy`, `setAverageIPScalarRange`, `setComputeNormalFromOpacity`, `setFilterMode`, `setFilterModeToNormalized`, `setFilterModeToOff`, `setFilterModeToRaw`, `setGlobalIlluminationReach`, `setIpScalarRange`, `setIpScalarRangeFrom`, `setLAOKernelRadius`, `setLAOKernelSize`, `setLocalAmbientOcclusion`, `setPreferSizeOverAccuracy`, `setVolumetricScatteringBlending`.
4
1
  ## From 31.x to 32
5
2
 
6
3
  - **vtkMapper**: remove `mapScalarsToTexture` from the public API. The function becomes protected and its API changes. This shouldn't cause any issue in most cases.
@@ -83,6 +83,23 @@ export interface vtkDataArray extends vtkObject {
83
83
  */
84
84
  setRange(rangeValue: vtkRange, componentIndex: number): Range;
85
85
 
86
+ /**
87
+ * Returns an array of the ranges for each component of the DataArray.
88
+ * Defaults to computing all the ranges if they aren't already computed.
89
+ *
90
+ * If the number of components is greater than 1, the last element in the
91
+ * ranges array is the min,max magnitude of the dataset. This is the same as
92
+ * calling `getRange(-1)`.
93
+ *
94
+ * Passing `getRanges(false)` will return a clone of the ranges that have
95
+ * already been computed. This is useful when you want to avoid recomputing
96
+ * the ranges, which can be expensive.
97
+ *
98
+ * @param {boolean} [computeRanges] (default: true)
99
+ * @returns {vtkRange[]}
100
+ */
101
+ getRanges(computeRanges: boolean): vtkRange[];
102
+
86
103
  /**
87
104
  * Set the given tuple at the given index.
88
105
  * @param {Number} idx
@@ -268,6 +268,35 @@ function vtkDataArray(publicAPI, model) {
268
268
  model.rangeTuple[1] = range.max;
269
269
  return model.rangeTuple;
270
270
  };
271
+ publicAPI.getRanges = function () {
272
+ let computeRanges = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
273
+ if (!computeRanges) {
274
+ return structuredClone(model.ranges);
275
+ }
276
+ /** @type {import('../../../interfaces').vtkRange[]} */
277
+ const ranges = [];
278
+ for (let i = 0; i < model.numberOfComponents; i++) {
279
+ const [min, max] = publicAPI.getRange(i);
280
+ /** @type {import('../../../interfaces').vtkRange} */
281
+ const range = {
282
+ min,
283
+ max
284
+ };
285
+ ranges.push(range);
286
+ }
287
+ // where the number of components is greater than 1, the last element in
288
+ // the range array is the min,max magnitude of the entire dataset.
289
+ if (model.numberOfComponents > 1) {
290
+ const [min, max] = publicAPI.getRange(-1);
291
+ /** @type {import('../../../interfaces').vtkRange} */
292
+ const range = {
293
+ min,
294
+ max
295
+ };
296
+ ranges.push(range);
297
+ }
298
+ return ranges;
299
+ };
271
300
  publicAPI.setTuple = (idx, tuple) => {
272
301
  const offset = idx * model.numberOfComponents;
273
302
  for (let i = 0; i < model.numberOfComponents; i++) {
@@ -426,12 +455,19 @@ function vtkDataArray(publicAPI, model) {
426
455
  }
427
456
  return sortedObj;
428
457
  };
458
+
459
+ /**
460
+ * @param {import("./index").vtkDataArray} other
461
+ */
429
462
  publicAPI.deepCopy = other => {
430
463
  // Retain current dataType and array reference before shallowCopy call.
431
464
  const currentType = publicAPI.getDataType();
432
465
  const currentArray = model.values;
433
466
  publicAPI.shallowCopy(other);
434
467
 
468
+ // set the ranges
469
+ model.ranges = structuredClone(other.getRanges());
470
+
435
471
  // Avoid array reallocation if size already sufficient
436
472
  // and dataTypes match.
437
473
  if (currentArray?.length >= other.getNumberOfValues() && currentType === other.getDataType()) {
@@ -9,9 +9,14 @@ const ScalarMappingTarget = {
9
9
  RGB: 3,
10
10
  RGBA: 4
11
11
  };
12
+ const Scale = {
13
+ LINEAR: 0,
14
+ LOG10: 1
15
+ };
12
16
  var vtkScalarsToColors = {
13
17
  VectorMode,
14
- ScalarMappingTarget
18
+ ScalarMappingTarget,
19
+ Scale
15
20
  };
16
21
 
17
- export { ScalarMappingTarget, VectorMode, vtkScalarsToColors as default };
22
+ export { ScalarMappingTarget, Scale, VectorMode, vtkScalarsToColors as default };
@@ -5,6 +5,7 @@ import Constants from '../../Rendering/Core/Mapper/Constants.js';
5
5
 
6
6
  const {
7
7
  ScalarMappingTarget,
8
+ Scale,
8
9
  VectorMode
9
10
  } = vtkScalarsToColors$2;
10
11
  const {
@@ -469,7 +470,8 @@ const DEFAULT_VALUES = {
469
470
  mappingRange: null,
470
471
  annotationArray: null,
471
472
  annotatedValueMap: null,
472
- indexedLookup: false
473
+ indexedLookup: false,
474
+ scale: Scale.LINEAR
473
475
  };
474
476
 
475
477
  // ----------------------------------------------------------------------------
@@ -122,6 +122,87 @@ export interface vtkAbstractImageMapper extends vtkAbstractMapper3D {
122
122
  * @param customDisplayExtent
123
123
  */
124
124
  setCustomDisplayExtentFrom(customDisplayExtent: number[]): boolean;
125
+
126
+ /**
127
+ * Set the opacity texture width.
128
+ *
129
+ * The default width (1024) should be fine in most instances.
130
+ * Only set this property if your opacity function range width is
131
+ * larger than 1024.
132
+ *
133
+ * A reasonable max texture size would be either 2048 or 4096, as those
134
+ * widths are supported by the vast majority of devices. Any width larger
135
+ * than that will have issues with device support.
136
+ *
137
+ * Specifying a width that is less than or equal to 0 will use the largest
138
+ * possible texture width on the device. Use this with caution! The max texture
139
+ * width of one device may not be the same for another device.
140
+ *
141
+ * You can find more information about supported texture widths at the following link:
142
+ * https://web3dsurvey.com/webgl/parameters/MAX_TEXTURE_SIZE
143
+ *
144
+ * @param {Number} width the texture width (defaults to 1024)
145
+ */
146
+ setOpacityTextureWidth(width: number): boolean;
147
+
148
+ /**
149
+ * Get the opacity texture width.
150
+ */
151
+ getOpacityTextureWidth(): number;
152
+
153
+ /**
154
+ * Set the color texture width.
155
+ *
156
+ * The default width (1024) should be fine in most instances.
157
+ * Only set this property if your color transfer function range width is
158
+ * larger than 1024.
159
+ *
160
+ * A reasonable max texture size would be either 2048 or 4096, as those
161
+ * widths are supported by the vast majority of devices. Any width larger
162
+ * than that will have issues with device support.
163
+ *
164
+ * Specifying a width that is less than or equal to 0 will use the largest
165
+ * possible texture width on the device. Use this with caution! The max texture
166
+ * width of one device may not be the same for another device.
167
+ *
168
+ * You can find more information about supported texture widths at the following link:
169
+ * https://web3dsurvey.com/webgl/parameters/MAX_TEXTURE_SIZE
170
+ *
171
+ * @param {Number} width the texture width (defaults to 1024)
172
+ */
173
+ setColorTextureWidth(width: number): boolean;
174
+
175
+ /**
176
+ * Get the color texture width.
177
+ */
178
+ getColorTextureWidth(): number;
179
+
180
+ /**
181
+ * Set the label outline texture width.
182
+ *
183
+ * The default width (1024) should be fine in most instances.
184
+ * Only set this property if you have more than 1024 labels
185
+ * that you want to render with thickness.
186
+ *
187
+ * A reasonable max texture size would be either 2048 or 4096, as those
188
+ * widths are supported by the vast majority of devices. Any width larger
189
+ * than that will have issues with device support.
190
+ *
191
+ * Specifying a width that is less than or equal to 0 will use the largest
192
+ * possible texture width on the device. Use this with caution! The max texture
193
+ * width of one device may not be the same for another device.
194
+ *
195
+ * You can find more information about supported texture widths at the following link:
196
+ * https://web3dsurvey.com/webgl/parameters/MAX_TEXTURE_SIZE
197
+ *
198
+ * @param {Number} width the texture width (defaults to 1024)
199
+ */
200
+ setLabelOutlineTextureWidth(width: number): boolean;
201
+
202
+ /**
203
+ * Get the label outline texture width.
204
+ */
205
+ getLabelOutlineTextureWidth(): number;
125
206
  }
126
207
 
127
208
  /**
@@ -24,7 +24,10 @@ const DEFAULT_VALUES = {
24
24
  slice: 0,
25
25
  customDisplayExtent: [0, 0, 0, 0, 0, 0],
26
26
  useCustomExtents: false,
27
- backgroundColor: [0, 0, 0, 1]
27
+ backgroundColor: [0, 0, 0, 1],
28
+ colorTextureWidth: 1024,
29
+ opacityTextureWidth: 1024,
30
+ labelOutlineTextureWidth: 1024
28
31
  };
29
32
 
30
33
  // ----------------------------------------------------------------------------
@@ -35,7 +38,7 @@ function extend(publicAPI, model) {
35
38
 
36
39
  // Build VTK API
37
40
  vtkAbstractMapper3D.extend(publicAPI, model, initialValues);
38
- macro.setGet(publicAPI, model, ['slice', 'useCustomExtents']);
41
+ macro.setGet(publicAPI, model, ['slice', 'useCustomExtents', 'colorTextureWidth', 'opacityTextureWidth', 'labelOutlineTextureWidth']);
39
42
  macro.setGetArray(publicAPI, model, ['customDisplayExtent'], 6);
40
43
  macro.setGetArray(publicAPI, model, ['backgroundColor'], 4);
41
44
  vtkAbstractImageMapper(publicAPI, model);
@@ -1,6 +1,6 @@
1
1
  import { vtkObject } from './../../interfaces';
2
2
  import { Vector3 } from './../../types';
3
- import vtkActor from './Actor';
3
+ import vtkProp3D from './Prop3D';
4
4
  import vtkRenderer from './Renderer';
5
5
 
6
6
  /**
@@ -10,8 +10,8 @@ export interface IAbstractPickerInitialValues {
10
10
  renderer?: vtkRenderer;
11
11
  selectionPoint?: Vector3;
12
12
  pickPosition?: Vector3;
13
- pickFromList?: number;
14
- pickList?: vtkActor[];
13
+ pickFromList?: boolean;
14
+ pickList?: vtkProp3D[];
15
15
  }
16
16
 
17
17
  /**
@@ -20,15 +20,15 @@ export interface IAbstractPickerInitialValues {
20
20
  export interface vtkAbstractPicker extends vtkObject {
21
21
  /**
22
22
  *
23
- * @param {vtkActor} actor
23
+ * @param {vtkProp3D} prop
24
24
  */
25
- addPickList(actor: vtkActor): void;
25
+ addPickList(prop: vtkProp3D): void;
26
26
 
27
27
  /**
28
28
  *
29
- * @param {vtkActor} actor
29
+ * @param {vtkProp3D} prop
30
30
  */
31
- deletePickList(actor: vtkActor): void;
31
+ deletePickList(prop: vtkProp3D): void;
32
32
 
33
33
  /**
34
34
  *
@@ -38,7 +38,7 @@ export interface vtkAbstractPicker extends vtkObject {
38
38
  /**
39
39
  *
40
40
  */
41
- getPickList(): boolean;
41
+ getPickList(): vtkProp3D[];
42
42
 
43
43
  /**
44
44
  * Get the picked position
@@ -82,17 +82,17 @@ export interface vtkAbstractPicker extends vtkObject {
82
82
 
83
83
  /**
84
84
  *
85
- * @param {Number} pickFromList
86
- * @default 0
85
+ * @param {Boolean} pickFromList
86
+ * @default false
87
87
  */
88
- setPickFromList(pickFromList: number): boolean;
88
+ setPickFromList(pickFromList: boolean): boolean;
89
89
 
90
90
  /**
91
91
  *
92
- * @param {vtkActor[]} pickList
92
+ * @param {vtkProp3D[]} pickList
93
93
  * @default []
94
94
  */
95
- setPickList(pickList: vtkActor[]): boolean;
95
+ setPickList(pickList: vtkProp3D[]): boolean;
96
96
  }
97
97
 
98
98
  /**
@@ -38,7 +38,7 @@ const DEFAULT_VALUES = {
38
38
  renderer: null,
39
39
  selectionPoint: [0.0, 0.0, 0.0],
40
40
  pickPosition: [0.0, 0.0, 0.0],
41
- pickFromList: 0,
41
+ pickFromList: false,
42
42
  pickList: []
43
43
  };
44
44
 
@@ -36,6 +36,12 @@ export interface vtkActor extends vtkProp3D {
36
36
  */
37
37
  getBackfaceProperty(): vtkProperty;
38
38
 
39
+ /**
40
+ * Get the bounds for this mapper as [xmin, xmax, ymin, ymax,zmin, zmax].
41
+ * @return {Bounds} The bounds for the mapper.
42
+ */
43
+ getBounds(): Bounds;
44
+
39
45
  /**
40
46
  * Check whether the opaque is forced or not.
41
47
  */
@@ -57,6 +63,16 @@ export interface vtkActor extends vtkProp3D {
57
63
  */
58
64
  getMapper(): Nullable<vtkMapper>;
59
65
 
66
+ /**
67
+ * Get the property object that controls this actors surface
68
+ * properties. This should be an instance of a vtkProperty object. Every
69
+ * actor must have a property associated with it. If one isn’t specified,
70
+ * then one will be generated automatically. Multiple actors can share one
71
+ * property object.
72
+ * @return {vtkProperty} The property object
73
+ */
74
+ getProperty(): vtkProperty;
75
+
60
76
  /**
61
77
  * Check whether if the actor supports selection
62
78
  * @return {Boolean} true if the actor support selection.
@@ -95,12 +111,11 @@ export interface vtkActor extends vtkProp3D {
95
111
  */
96
112
  setMapper(mapper: vtkMapper): boolean;
97
113
 
98
- // Inherited from vtkProp3D, but takes a vtkProperty instead of a generic vtkObject
99
- getProperty(mapperInputPort?: number): vtkProperty;
100
- getProperties(): vtkProperty[];
101
- setProperty(mapperInputPort: number, property: vtkProperty): boolean;
114
+ /**
115
+ * Set the property object that controls this actors surface properties.
116
+ * @param {vtkProperty} property The vtkProperty instance.
117
+ */
102
118
  setProperty(property: vtkProperty): boolean;
103
- setProperties(properties: vtkProperty[]): boolean;
104
119
  }
105
120
 
106
121
  /**
@@ -1,7 +1,13 @@
1
+ import { mat4, vec3 } from 'gl-matrix';
1
2
  import { m as macro } from '../../macros2.js';
3
+ import vtkBoundingBox from '../../Common/DataModel/BoundingBox.js';
2
4
  import vtkProp3D from './Prop3D.js';
3
5
  import vtkProperty from './Property.js';
4
6
 
7
+ const {
8
+ vtkDebugMacro
9
+ } = macro;
10
+
5
11
  // ----------------------------------------------------------------------------
6
12
  // vtkActor methods
7
13
  // ----------------------------------------------------------------------------
@@ -23,11 +29,11 @@ function vtkActor(publicAPI, model) {
23
29
  return false;
24
30
  }
25
31
  // make sure we have a property
26
- if (!model.properties[0]) {
32
+ if (!model.property) {
27
33
  // force creation of a property
28
34
  publicAPI.getProperty();
29
35
  }
30
- let isOpaque = model.properties[0].getOpacity() >= 1.0;
36
+ let isOpaque = model.property.getOpacity() >= 1.0;
31
37
 
32
38
  // are we using an opaque texture, if any?
33
39
  isOpaque = isOpaque && (!model.texture || !model.texture.isTranslucent());
@@ -41,17 +47,71 @@ function vtkActor(publicAPI, model) {
41
47
  return false;
42
48
  }
43
49
  // make sure we have a property
44
- if (!model.properties[0]) {
50
+ if (model.property === null) {
45
51
  // force creation of a property
46
- publicAPI.getProperty();
52
+ publicAPI.setProperty(publicAPI.makeProperty());
47
53
  }
48
54
 
49
55
  // is this actor opaque ?
50
56
  return !publicAPI.getIsOpaque();
51
57
  };
52
58
  publicAPI.makeProperty = vtkProperty.newInstance;
59
+ publicAPI.getProperty = () => {
60
+ if (model.property === null) {
61
+ model.property = publicAPI.makeProperty();
62
+ }
63
+ return model.property;
64
+ };
65
+ publicAPI.getBounds = () => {
66
+ if (model.mapper === null) {
67
+ return model.bounds;
68
+ }
69
+
70
+ // Check for the special case when the mapper's bounds are unknown
71
+ const bds = model.mapper.getBounds();
72
+ if (!bds || bds.length !== 6) {
73
+ return bds;
74
+ }
75
+
76
+ // Check for the special case when the actor is empty.
77
+ if (bds[0] > bds[1]) {
78
+ model.mapperBounds = bds.concat(); // copy the mapper's bounds
79
+ model.bounds = [1, -1, 1, -1, 1, -1];
80
+ model.boundsMTime.modified();
81
+ return bds;
82
+ }
83
+
84
+ // Check if we have cached values for these bounds - we cache the
85
+ // values returned by model.mapper.getBounds() and we store the time
86
+ // of caching. If the values returned this time are different, or
87
+ // the modified time of this class is newer than the cached time,
88
+ // then we need to rebuild.
89
+ if (!model.mapperBounds || bds[0] !== model.mapperBounds[0] || bds[1] !== model.mapperBounds[1] || bds[2] !== model.mapperBounds[2] || bds[3] !== model.mapperBounds[3] || bds[4] !== model.mapperBounds[4] || bds[5] !== model.mapperBounds[5] || publicAPI.getMTime() > model.boundsMTime.getMTime()) {
90
+ vtkDebugMacro('Recomputing bounds...');
91
+ model.mapperBounds = bds.concat(); // copy the mapper's bounds
92
+ const bbox = [];
93
+ vtkBoundingBox.getCorners(bds, bbox);
94
+ publicAPI.computeMatrix();
95
+ const tmp4 = new Float64Array(16);
96
+ mat4.transpose(tmp4, model.matrix);
97
+ bbox.forEach(pt => vec3.transformMat4(pt, pt, tmp4));
98
+
99
+ /* eslint-disable no-multi-assign */
100
+ model.bounds[0] = model.bounds[2] = model.bounds[4] = Number.MAX_VALUE;
101
+ model.bounds[1] = model.bounds[3] = model.bounds[5] = -Number.MAX_VALUE;
102
+ /* eslint-enable no-multi-assign */
103
+
104
+ model.bounds = model.bounds.map((d, i) => i % 2 === 0 ? bbox.reduce((a, b) => a > b[i / 2] ? b[i / 2] : a, d) : bbox.reduce((a, b) => a < b[(i - 1) / 2] ? b[(i - 1) / 2] : a, d));
105
+ model.boundsMTime.modified();
106
+ }
107
+ return model.bounds;
108
+ };
53
109
  publicAPI.getMTime = () => {
54
110
  let mt = superClass.getMTime();
111
+ if (model.property !== null) {
112
+ const time = model.property.getMTime();
113
+ mt = time > mt ? time : mt;
114
+ }
55
115
  if (model.backfaceProperty !== null) {
56
116
  const time = model.backfaceProperty.getMTime();
57
117
  mt = time > mt ? time : mt;
@@ -86,9 +146,11 @@ function vtkActor(publicAPI, model) {
86
146
 
87
147
  const DEFAULT_VALUES = {
88
148
  mapper: null,
149
+ property: null,
89
150
  backfaceProperty: null,
90
151
  forceOpaque: false,
91
- forceTranslucent: false
152
+ forceTranslucent: false,
153
+ bounds: [1, -1, 1, -1, 1, -1]
92
154
  };
93
155
 
94
156
  // ----------------------------------------------------------------------------
@@ -105,6 +167,7 @@ function extend(publicAPI, model) {
105
167
  macro.obj(model.boundsMTime);
106
168
 
107
169
  // Build VTK API
170
+ macro.set(publicAPI, model, ['property']);
108
171
  macro.setGet(publicAPI, model, ['backfaceProperty', 'forceOpaque', 'forceTranslucent', 'mapper']);
109
172
 
110
173
  // Object methods
@@ -54,6 +54,28 @@ export interface vtkActor2D extends vtkProp {
54
54
  */
55
55
  getMapper(): vtkMapper2D;
56
56
 
57
+ /**
58
+ * Set the layer number for this 2D actor.
59
+ * The scenegraph uses this layer number to sort actor 2D overlays/underlays on top of each other.
60
+ * The actor2D with the highest layer number is going to be rendered at the very front i.e. it is
61
+ * the top-most layer.
62
+ * If two actor2D instances share the same layer number, they are rendered in the order in which
63
+ * they were added to the renderer via `addActor` or `addActor2D`.
64
+ * By default, each actor2D has a layer number of 0.
65
+ */
66
+ setLayerNumber(layer: number): void;
67
+
68
+ /**
69
+ * Get the layer number for this 2D actor.
70
+ * The scenegraph uses this layer number to sort actor 2D overlays/underlays on top of each other.
71
+ * The actor2D with the highest layer number is going to be rendered at the very front i.e. it is
72
+ * the top-most layer.
73
+ * If two actor2D instances share the same layer number, they are rendered in the order in which
74
+ * they were added to the renderer via `addActor` or `addActor2D`.
75
+ * By default, each actor2D has a layer number of 0.
76
+ */
77
+ getLayerNumber(): number;
78
+
57
79
  /**
58
80
  *
59
81
  */
@@ -145,7 +145,7 @@ function extend(publicAPI, model) {
145
145
 
146
146
  // Build VTK API
147
147
  macro.set(publicAPI, model, ['property']);
148
- macro.setGet(publicAPI, model, ['mapper']);
148
+ macro.setGet(publicAPI, model, ['mapper', 'layerNumber']);
149
149
 
150
150
  // Object methods
151
151
  vtkActor2D(publicAPI, model);
@@ -219,7 +219,10 @@ function vtkCellPicker(publicAPI, model) {
219
219
 
220
220
  // calculate opacity table
221
221
  const numIComps = 1;
222
- const oWidth = 1024;
222
+ let oWidth = mapper.getOpacityTextureWidth();
223
+ if (oWidth <= 0) {
224
+ oWidth = 1024;
225
+ }
223
226
  const tmpTable = new Float32Array(oWidth);
224
227
  const opacityArray = new Float32Array(oWidth);
225
228
  let ofun;
@@ -400,13 +400,18 @@ function vtkColorTransferFunction(publicAPI, model) {
400
400
  publicAPI.getColor(x, rgb);
401
401
  return rgb[2];
402
402
  };
403
+ publicAPI.logScaleEnabled = () => model.scale === Scale.LOG10;
404
+ publicAPI.usingLogScale = () => publicAPI.logScaleEnabled() && model.mappingRange[0] > 0.0;
403
405
 
404
406
  //----------------------------------------------------------------------------
405
407
  // Returns a table of RGB colors at regular intervals along the function
406
408
  publicAPI.getTable = (xStart_, xEnd_, size, table) => {
409
+ // Note: This requires range[0] <= range[1].
410
+ const usingLogScale = publicAPI.usingLogScale();
411
+
407
412
  // To handle BigInt limitation
408
- const xStart = Number(xStart_);
409
- const xEnd = Number(xEnd_);
413
+ const xStart = usingLogScale ? Math.log10(Number(xStart_)) : Number(xStart_);
414
+ const xEnd = usingLogScale ? Math.log10(Number(xEnd_)) : Number(xEnd_);
410
415
 
411
416
  // Special case: If either the start or end is a NaN, then all any
412
417
  // interpolation done on them is also a NaN. Therefore, fill the table with
@@ -443,17 +448,9 @@ function vtkColorTransferFunction(publicAPI, model) {
443
448
  const tmpVec = [];
444
449
 
445
450
  // If the scale is logarithmic, make sure the range is valid.
446
- let usingLogScale = model.scale === Scale.LOG10;
447
- if (usingLogScale) {
448
- // Note: This requires range[0] <= range[1].
449
- usingLogScale = model.mappingRange[0] > 0.0;
450
- }
451
- let logStart = 0.0;
452
- let logEnd = 0.0;
453
- let logX = 0.0;
451
+ let scaledMappingRange = model.mappingRange;
454
452
  if (usingLogScale) {
455
- logStart = Math.log10(xStart);
456
- logEnd = Math.log10(xEnd);
453
+ scaledMappingRange = [Math.log10(model.mappingRange[0]), Math.log10(model.mappingRange[1])];
457
454
  }
458
455
 
459
456
  // For each table entry
@@ -465,15 +462,7 @@ function vtkColorTransferFunction(publicAPI, model) {
465
462
  // it halfway between start and end (usually start and end will
466
463
  // be the same in this case)
467
464
  if (size > 1) {
468
- if (usingLogScale) {
469
- logX = logStart + i / (size - 1.0) * (logEnd - logStart);
470
- x = 10.0 ** logX;
471
- } else {
472
- x = xStart + i / (size - 1.0) * (xEnd - xStart);
473
- }
474
- } else if (usingLogScale) {
475
- logX = 0.5 * (logStart + logEnd);
476
- x = 10.0 ** logX;
465
+ x = xStart + i / (size - 1.0) * (xEnd - xStart);
477
466
  } else {
478
467
  x = 0.5 * (xStart + xEnd);
479
468
  }
@@ -482,7 +471,7 @@ function vtkColorTransferFunction(publicAPI, model) {
482
471
  // discretize (round down to the closest integer),
483
472
  // then map back to mappingRange
484
473
  if (model.discretize) {
485
- const range = model.mappingRange;
474
+ const range = scaledMappingRange;
486
475
  if (x >= range[0] && x <= range[1]) {
487
476
  const numberOfValues = model.numberOfValues;
488
477
  const deltaRange = range[1] - range[0];
@@ -509,10 +498,6 @@ function vtkColorTransferFunction(publicAPI, model) {
509
498
  if (idx < numNodes) {
510
499
  x1 = model.nodes[idx - 1].x;
511
500
  x2 = model.nodes[idx].x;
512
- if (usingLogScale) {
513
- x1 = Math.log10(x1);
514
- x2 = Math.log10(x2);
515
- }
516
501
  rgb1[0] = model.nodes[idx - 1].r;
517
502
  rgb2[0] = model.nodes[idx].r;
518
503
  rgb1[1] = model.nodes[idx - 1].g;
@@ -537,7 +522,7 @@ function vtkColorTransferFunction(publicAPI, model) {
537
522
  }
538
523
 
539
524
  // Are we at or past the end? If so, just use the last value
540
- if (x > model.mappingRange[1]) {
525
+ if (x > scaledMappingRange[1]) {
541
526
  table[tidx] = 0.0;
542
527
  table[tidx + 1] = 0.0;
543
528
  table[tidx + 2] = 0.0;
@@ -552,7 +537,7 @@ function vtkColorTransferFunction(publicAPI, model) {
552
537
  table[tidx + 2] = lastB;
553
538
  }
554
539
  }
555
- } else if (x < model.mappingRange[0] || isInf(x) && x < 0) {
540
+ } else if (x < scaledMappingRange[0] || isInf(x) && x < 0) {
556
541
  // we are before the first node? If so, duplicate this node's values.
557
542
  // We have to deal with -inf here
558
543
  table[tidx] = 0.0;
@@ -586,11 +571,7 @@ function vtkColorTransferFunction(publicAPI, model) {
586
571
  // sharpness to get the curve shape we want and to have
587
572
  // it pass through (y1+y2)/2 at the midpoint.
588
573
  let s = 0.0;
589
- if (usingLogScale) {
590
- s = (logX - x1) / (x2 - x1);
591
- } else {
592
- s = (x - x1) / (x2 - x1);
593
- }
574
+ s = (x - x1) / (x2 - x1);
594
575
 
595
576
  // Readjust based on the midpoint - linear adjustment
596
577
  if (s < midpoint) {
@@ -975,7 +956,9 @@ function vtkColorTransferFunction(publicAPI, model) {
975
956
  //----------------------------------------------------------------------------
976
957
  publicAPI.setMappingRange = (min, max) => {
977
958
  const range = [min, max];
959
+ const scaledRange = [min, max];
978
960
  const originalRange = publicAPI.getRange();
961
+ const logScaleEnabled = publicAPI.logScaleEnabled();
979
962
  if (originalRange[1] === range[1] && originalRange[0] === range[0]) {
980
963
  return;
981
964
  }
@@ -983,8 +966,16 @@ function vtkColorTransferFunction(publicAPI, model) {
983
966
  vtkErrorMacro('attempt to set zero width color range');
984
967
  return;
985
968
  }
986
- const scale = (range[1] - range[0]) / (originalRange[1] - originalRange[0]);
987
- const shift = range[0] - originalRange[0] * scale;
969
+ if (logScaleEnabled) {
970
+ if (range[0] <= 0.0) {
971
+ console.warn('attempt to set log scale color range with non-positive minimum');
972
+ } else {
973
+ scaledRange[0] = Math.log10(range[0]);
974
+ scaledRange[1] = Math.log10(range[1]);
975
+ }
976
+ }
977
+ const scale = (scaledRange[1] - scaledRange[0]) / (originalRange[1] - originalRange[0]);
978
+ const shift = scaledRange[0] - originalRange[0] * scale;
988
979
  for (let i = 0; i < model.nodes.length; ++i) {
989
980
  model.nodes[i].x = model.nodes[i].x * scale + shift;
990
981
  }