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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/Common/Core/DataArray.d.ts +4 -0
  2. package/Common/Core/DataArray.js +3 -0
  3. package/Common/Core/Math/index.js +1 -1
  4. package/Common/Core/Math.js +1 -1
  5. package/Common/Core/URLExtract.js +2 -6
  6. package/Common/DataModel/Line.js +1 -0
  7. package/Common/DataModel/PolyLine.js +4 -0
  8. package/Filters/Core/ThresholdPoints.d.ts +72 -0
  9. package/Filters/Core/ThresholdPoints.js +219 -0
  10. package/Filters/General/ContourTriangulator/helper.js +1 -1
  11. package/IO/Core/DataAccessHelper/JSZipDataAccessHelper.js +1 -1
  12. package/IO/Geometry/DracoReader.d.ts +4 -4
  13. package/IO/Geometry/DracoReader.js +154 -105
  14. package/IO/Geometry/GLTFImporter/Animations.js +239 -0
  15. package/IO/Geometry/GLTFImporter/Constants.js +87 -0
  16. package/IO/Geometry/GLTFImporter/Decoder.js +69 -0
  17. package/IO/Geometry/GLTFImporter/Extensions.js +110 -0
  18. package/IO/Geometry/GLTFImporter/ORMTexture.worker.js +42 -0
  19. package/IO/Geometry/GLTFImporter/Parser.js +359 -0
  20. package/IO/Geometry/GLTFImporter/Reader.js +518 -0
  21. package/IO/Geometry/GLTFImporter/Utils.js +165 -0
  22. package/IO/Geometry/GLTFImporter.d.ts +266 -0
  23. package/IO/Geometry/GLTFImporter.js +245 -0
  24. package/IO/Geometry/IFCImporter.d.ts +163 -0
  25. package/IO/Geometry/IFCImporter.js +270 -0
  26. package/IO/Geometry/STLReader.d.ts +14 -0
  27. package/IO/Geometry/STLReader.js +57 -1
  28. package/IO/Geometry.js +5 -1
  29. package/IO/Image/HDRReader/Utils.js +1 -1
  30. package/IO/Image/HDRReader.js +1 -1
  31. package/IO/Image/TGAReader/Constants.js +28 -0
  32. package/IO/Image/TGAReader.d.ts +121 -0
  33. package/IO/Image/TGAReader.js +418 -0
  34. package/IO/Image/TIFFReader.d.ts +133 -0
  35. package/IO/Image/TIFFReader.js +144 -0
  36. package/IO/Image.js +5 -1
  37. package/IO/XML/XMLPolyDataWriter.js +1 -0
  38. package/Interaction/Manipulators/MouseCameraTrackballRollManipulator.js +1 -1
  39. package/Interaction/Style/InteractorStyleTrackballCamera.js +1 -1
  40. package/Rendering/Core/Glyph3DMapper.d.ts +45 -29
  41. package/Rendering/Core/ImageCPRMapper.js +1 -1
  42. package/Rendering/Core/ImageProperty.d.ts +22 -0
  43. package/Rendering/Core/PointPicker.js +10 -1
  44. package/Rendering/Core/Prop3D.js +1 -1
  45. package/Rendering/Core/RenderWindowInteractor.d.ts +1 -1
  46. package/Rendering/Core/RenderWindowInteractor.js +1 -1
  47. package/Rendering/Misc/CanvasView.js +4 -2
  48. package/Rendering/Misc/RemoteView.d.ts +9 -3
  49. package/Rendering/Misc/RemoteView.js +7 -3
  50. package/Rendering/Misc/SynchronizableRenderWindow/ObjectManager.d.ts +1 -1
  51. package/Rendering/OpenGL/ImageMapper.js +14 -7
  52. package/Rendering/OpenGL/Texture/supportsNorm16Linear.js +97 -0
  53. package/Rendering/OpenGL/Texture.js +18 -11
  54. package/Widgets/Widgets3D/AngleWidget/behavior.js +2 -0
  55. package/Widgets/Widgets3D/InteractiveOrientationWidget.js +1 -1
  56. package/Widgets/Widgets3D/ResliceCursorWidget/behavior.js +17 -0
  57. package/Widgets/Widgets3D/ResliceCursorWidget/helpers.js +1 -0
  58. package/Widgets/Widgets3D/ShapeWidget/behavior.js +3 -0
  59. package/_virtual/rollup-plugin-worker-loader__module_Sources/IO/Geometry/GLTFImporter/ORMTexture.worker.js +296 -0
  60. package/index.d.ts +5 -0
  61. package/package.json +12 -10
@@ -36,6 +36,7 @@ function vtkXMLPolyDataWriter(publicAPI, model) {
36
36
  });
37
37
  publicAPI.processDataSetAttributes(piece, 'PointData', dataObject.getPointData());
38
38
  publicAPI.processDataSetAttributes(piece, 'CellData', dataObject.getCellData());
39
+ publicAPI.processDataSetAttributes(piece, 'FieldData', dataObject.getFieldData());
39
40
  publicAPI.processDataArray(piece.ele('Points'), dataObject.getPoints());
40
41
  POLYDATA_FIELDS.forEach(cellType => {
41
42
  const cellTypeName = camelize(cellType);
@@ -2,7 +2,7 @@ import { mat4, vec3 } from 'gl-matrix';
2
2
  import { m as macro } from '../../macros2.js';
3
3
  import vtkCompositeCameraManipulator from './CompositeCameraManipulator.js';
4
4
  import vtkCompositeMouseManipulator from './CompositeMouseManipulator.js';
5
- import { r as radiansFromDegrees, C as degreesFromRadians } from '../../Common/Core/Math/index.js';
5
+ import { r as radiansFromDegrees, A as degreesFromRadians } from '../../Common/Core/Math/index.js';
6
6
 
7
7
  // ----------------------------------------------------------------------------
8
8
  // vtkMouseCameraTrackballRollManipulator methods
@@ -1,7 +1,7 @@
1
1
  import { m as macro } from '../../macros2.js';
2
2
  import vtkInteractorStyle from '../../Rendering/Core/InteractorStyle.js';
3
3
  import vtkInteractorStyleConstants from '../../Rendering/Core/InteractorStyle/Constants.js';
4
- import { C as degreesFromRadians } from '../../Common/Core/Math/index.js';
4
+ import { A as degreesFromRadians } from '../../Common/Core/Math/index.js';
5
5
  import { Device, Input } from '../../Rendering/Core/RenderWindowInteractor/Constants.js';
6
6
 
7
7
  const {
@@ -12,11 +12,11 @@ interface IPrimitiveCount {
12
12
  export interface IGlyph3DMapperInitialValues extends IMapperInitialValues {
13
13
  orient?: boolean;
14
14
  orientationMode?: OrientationModes;
15
- orientationArray?: number[];
15
+ orientationArray?: string;
16
16
  scaling?: boolean;
17
17
  scaleFactor?: number;
18
18
  scaleMode?: ScaleModes;
19
- scaleArray?: number[];
19
+ scaleArray?: string;
20
20
  matrixArray?: number[];
21
21
  normalArray?: number[];
22
22
  colorArray?: number[];
@@ -24,29 +24,26 @@ export interface IGlyph3DMapperInitialValues extends IMapperInitialValues {
24
24
 
25
25
  export interface vtkGlyph3DMapper extends vtkMapper {
26
26
  /**
27
- * An orientation array is a vtkDataArray with 3 components. The first
28
- * component is the angle of rotation along the X axis. The second component
29
- * is the angle of rotation along the Y axis. The third component is the
30
- * angle of rotation along the Z axis. Orientation is specified in X,Y,Z
31
- * order but the rotations are performed in Z,X an Y.
32
- *
33
- * This definition is compliant with SetOrientation method on vtkProp3D.
27
+ * Get the bounds for this mapper as [xmin, xmax, ymin, ymax,zmin, zmax].
28
+ * @return {Bounds} The bounds for the mapper.
29
+ */
30
+ getBounds(): Bounds;
31
+
32
+ /**
34
33
  *
35
- * By using vector or normal there is a degree of freedom or rotation left
36
- * (underconstrained). With the orientation array, there is no degree of
37
- * freedom left.
38
34
  */
39
- getOrientationMode(): OrientationModes;
35
+ buildArrays(): void;
40
36
 
41
37
  /**
42
- * Get orientation as string
38
+ *
43
39
  */
44
- getOrientationModeAsString(): string;
40
+ getPrimitiveCount(): IPrimitiveCount;
45
41
 
46
42
  /**
47
- * Get orientation as array
43
+ * Get scale mode
44
+ * @default `SCALE_BY_MAGNITUDE`
48
45
  */
49
- getOrientationArrayData(): number[];
46
+ getScaleMode(): ScaleModes;
50
47
 
51
48
  /**
52
49
  * Get scale factor to scale object by.
@@ -54,15 +51,20 @@ export interface vtkGlyph3DMapper extends vtkMapper {
54
51
  getScaleFactor(): number;
55
52
 
56
53
  /**
57
- * Get scale mode
58
- * @default `SCALE_BY_MAGNITUDE`
54
+ * Get scale mode as string
59
55
  */
60
- getScaleMode(): ScaleModes;
56
+ getScaleModeAsString(): string;
61
57
 
62
58
  /**
63
- * Get scale mode as string
59
+ * Sets the name of the array to use as scale values.
60
+ * @param {String} arrayName Name of the array
64
61
  */
65
- getScaleModeAsString(): string;
62
+ setScaleArray(arrayName: Nullable<string>): boolean;
63
+
64
+ /**
65
+ * Gets the name of the array used as scale values.
66
+ */
67
+ getScaleArray(): string;
66
68
 
67
69
  /**
68
70
  * Get scale mode as array
@@ -70,20 +72,29 @@ export interface vtkGlyph3DMapper extends vtkMapper {
70
72
  getScaleArrayData(): number[];
71
73
 
72
74
  /**
73
- * Get the bounds for this mapper as [xmin, xmax, ymin, ymax,zmin, zmax].
74
- * @return {Bounds} The bounds for the mapper.
75
+ * An orientation array is a vtkDataArray with 3 components. The first
76
+ * component is the angle of rotation along the X axis. The second component
77
+ * is the angle of rotation along the Y axis. The third component is the
78
+ * angle of rotation along the Z axis. Orientation is specified in X,Y,Z
79
+ * order but the rotations are performed in Z,X an Y.
80
+ *
81
+ * This definition is compliant with SetOrientation method on vtkProp3D.
82
+ *
83
+ * By using vector or normal there is a degree of freedom or rotation left
84
+ * (underconstrained). With the orientation array, there is no degree of
85
+ * freedom left.
75
86
  */
76
- getBounds(): Bounds;
87
+ getOrientationMode(): OrientationModes;
77
88
 
78
89
  /**
79
- *
90
+ * Get orientation as string
80
91
  */
81
- buildArrays(): void;
92
+ getOrientationModeAsString(): string;
82
93
 
83
94
  /**
84
- *
95
+ * Get orientation as array
85
96
  */
86
- getPrimitiveCount(): IPrimitiveCount;
97
+ getOrientationArrayData(): number[];
87
98
 
88
99
  /**
89
100
  * Sets the name of the array to use as orientation.
@@ -91,6 +102,11 @@ export interface vtkGlyph3DMapper extends vtkMapper {
91
102
  */
92
103
  setOrientationArray(arrayName: Nullable<string>): boolean;
93
104
 
105
+ /**
106
+ * Gets the name of the array used as orientation values.
107
+ */
108
+ getOrientationArray(): string;
109
+
94
110
  /**
95
111
  * Orientation mode indicates if the OrientationArray provides the direction
96
112
  * vector for the orientation or the rotations around each axes.
@@ -1,4 +1,4 @@
1
- import { vec3, mat4, quat } from 'gl-matrix';
1
+ import { quat, vec3, mat4 } from 'gl-matrix';
2
2
  import CoincidentTopologyHelper from './Mapper/CoincidentTopologyHelper.js';
3
3
  import vtkAbstractImageMapper from './AbstractImageMapper.js';
4
4
  import { m as macro } from '../../macros2.js';
@@ -94,6 +94,28 @@ export interface vtkImageProperty extends vtkObject {
94
94
  */
95
95
  getScalarOpacity(idx?: number): vtkPiecewiseFunction;
96
96
 
97
+ /**
98
+ * Enable label outline rendering.
99
+ * @param {Boolean} useLabelOutline
100
+ */
101
+ setUseLabelOutline(useLabelOutline: boolean): boolean;
102
+
103
+ /**
104
+ * Check if label outline rendering.
105
+ */
106
+ getUseLabelOutline(): boolean;
107
+
108
+ /**
109
+ * Set the 0 to 1 opacity of the label outline.
110
+ * @param {Number} opacity
111
+ */
112
+ setLabelOutlineOpacity(opacity: number): boolean;
113
+
114
+ /**
115
+ * Get the 0 to 1 opacity of the label outline.
116
+ */
117
+ getLabelOutlineOpacity(): number;
118
+
97
119
  /**
98
120
  * gets the label outline thickness
99
121
  */
@@ -80,6 +80,9 @@ function vtkPointPicker(publicAPI, model) {
80
80
  if (maxDist <= tolerance && maxDist < minPtDist) {
81
81
  // within tolerance
82
82
  minPtId = ptId;
83
+ x[0];
84
+ x[1];
85
+ x[2];
83
86
  minPtDist = maxDist;
84
87
  tMin = t;
85
88
  }
@@ -108,13 +111,19 @@ function vtkPointPicker(publicAPI, model) {
108
111
  if (maxDist <= tolerance && maxDist < minPtDist) {
109
112
  // within tolerance
110
113
  minPtId = ptId;
114
+ x[0];
115
+ x[1];
116
+ x[2];
111
117
  minPtDist = maxDist;
112
118
  tMin = t;
113
119
  }
114
120
  }
115
121
  }
116
122
  }
117
- model.pointId = minPtId;
123
+ if (minPtId > -1 && tMin < model.globalTMin) {
124
+ model.globalTMin = tMin;
125
+ model.pointId = minPtId;
126
+ }
118
127
  return tMin;
119
128
  };
120
129
  }
@@ -1,7 +1,7 @@
1
1
  import { mat4, quat } from 'gl-matrix';
2
2
  import { m as macro } from '../../macros2.js';
3
3
  import vtkBoundingBox from '../../Common/DataModel/BoundingBox.js';
4
- import { C as degreesFromRadians, r as radiansFromDegrees, a as areMatricesEqual } from '../../Common/Core/Math/index.js';
4
+ import { A as degreesFromRadians, r as radiansFromDegrees, a as areMatricesEqual } from '../../Common/Core/Math/index.js';
5
5
  import vtkProp from './Prop.js';
6
6
 
7
7
  const VTK_EPSILON = 1e-6;
@@ -63,7 +63,7 @@ export interface IRenderWindowInteractorInitialValues {
63
63
  mouseScrollDebounceByPass?: boolean;
64
64
  }
65
65
 
66
- interface IPosition {
66
+ export interface IPosition {
67
67
  type: string;
68
68
  }
69
69
 
@@ -1,5 +1,5 @@
1
1
  import { m as macro } from '../../macros2.js';
2
- import { C as degreesFromRadians } from '../../Common/Core/Math/index.js';
2
+ import { A as degreesFromRadians } from '../../Common/Core/Math/index.js';
3
3
  import Constants from './RenderWindowInteractor/Constants.js';
4
4
 
5
5
  const {
@@ -134,8 +134,10 @@ function extend(publicAPI, model) {
134
134
  Object.assign(model, DEFAULT_VALUES, initialValues);
135
135
 
136
136
  // Create internal instances
137
- model.canvas = document.createElement('canvas');
138
- model.canvas.style.width = '100%';
137
+ if (!model.canvas) {
138
+ model.canvas = document.createElement('canvas');
139
+ model.canvas.style.width = '100%';
140
+ }
139
141
 
140
142
  // Create internal bgImage
141
143
  model.bgImage = new Image();
@@ -13,21 +13,27 @@ interface IRemoteViewInitialValues {
13
13
  rpcGestureEvent?: any;
14
14
  rpcWheelEvent?: any;
15
15
  viewStream?: vtkViewStream;
16
+ canvasElement?: HTMLCanvasElement;
16
17
  }
17
18
 
18
19
  export interface vtkRemoteView extends vtkObject {
19
20
  /**
20
- * Get container element
21
+ * Get container HTML element
21
22
  */
22
23
  getContainer(): HTMLElement;
23
24
 
24
25
  /**
25
- *
26
+ * Get vtkViewStream object
26
27
  */
27
28
  getViewStream(): vtkViewStream;
28
29
 
29
30
  /**
30
- *
31
+ * Get the canvas HTML element
32
+ */
33
+ getCanvasElement(): HTMLCanvasElement;
34
+
35
+ /**
36
+ * Get the vtkCanvasView object
31
37
  */
32
38
  getCanvasView(): vtkCanvasView;
33
39
 
@@ -17,7 +17,9 @@ function vtkRemoteView(publicAPI, model) {
17
17
  model.classHierarchy.push('vtkRemoteView');
18
18
 
19
19
  // Constructor
20
- model.canvasView = vtkCanvasView.newInstance();
20
+ model.canvasView = vtkCanvasView.newInstance({
21
+ canvas: model.canvasElement
22
+ });
21
23
  model.interactorStyle = vtkInteractorStyleRemoteMouse.newInstance();
22
24
  model.interactor = vtkRenderWindowInteractor.newInstance();
23
25
  model.interactor.setView(model.canvasView);
@@ -60,6 +62,7 @@ function vtkRemoteView(publicAPI, model) {
60
62
  model.viewStream.delete();
61
63
  }
62
64
  }, publicAPI.delete);
65
+ publicAPI.getCanvasElement = () => model.canvasView.getCanvas();
63
66
 
64
67
  // --------------------------------------------------------------------------
65
68
  // remote handing
@@ -194,7 +197,8 @@ const DEFAULT_VALUES = {
194
197
  stillRatio: 1,
195
198
  rpcMouseEvent: 'viewport.mouse.interaction',
196
199
  rpcGestureEvent: null,
197
- rpcWheelEvent: null
200
+ rpcWheelEvent: null,
201
+ canvasElement: null
198
202
  };
199
203
 
200
204
  // ----------------------------------------------------------------------------
@@ -203,7 +207,7 @@ function extend(publicAPI, model) {
203
207
  let initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
204
208
  Object.assign(model, DEFAULT_VALUES, initialValues);
205
209
  macro.obj(publicAPI, model, initialValues);
206
- macro.get(publicAPI, model, ['container', 'viewStream', 'canvasView', 'interactor', 'interactorStyle', 'interactiveQuality', 'interactiveRatio', 'stillQuality', 'stillRatio']);
210
+ macro.get(publicAPI, model, ['container', 'viewStream', 'canvasView', 'interactor', 'interactorStyle', 'interactiveQuality', 'interactiveRatio', 'stillQuality', 'stillRatio', 'canvasElement']);
207
211
  macro.setGet(publicAPI, model, ['session', 'rpcMouseEvent', 'rpcGestureEvent', 'rpcWheelEvent']);
208
212
 
209
213
  // Object methods
@@ -1,6 +1,6 @@
1
1
  import { vtkObject } from './../../../interfaces';
2
2
  import { Nullable } from './../../../types';
3
- import { ISynchronizerContext, IViewState } from '..';
3
+ import { ISynchronizerContext, IViewState } from '../SynchronizableRenderWindow';
4
4
 
5
5
  export type BuilderFunction = <T extends vtkObject>(
6
6
  type: string,
@@ -167,9 +167,9 @@ function vtkOpenGLImageMapper(publicAPI, model) {
167
167
  // check for the outline thickness and opacity
168
168
  const vtkImageLabelOutline = actor.getProperty().getUseLabelOutline();
169
169
  if (vtkImageLabelOutline === true) {
170
- FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::LabelOutline::Dec', ['uniform int outlineThickness;', 'uniform float vpWidth;', 'uniform float vpHeight;', 'uniform float vpOffsetX;', 'uniform float vpOffsetY;', 'uniform mat4 PCWCMatrix;', 'uniform mat4 vWCtoIDX;', 'uniform ivec3 imageDimensions;']).result;
170
+ FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::LabelOutline::Dec', ['uniform int outlineThickness;', 'uniform float vpWidth;', 'uniform float vpHeight;', 'uniform float vpOffsetX;', 'uniform float vpOffsetY;', 'uniform mat4 PCWCMatrix;', 'uniform mat4 vWCtoIDX;', 'uniform ivec3 imageDimensions;', 'uniform int sliceAxis;']).result;
171
171
  FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::ImageLabelOutlineOn', '#define vtkImageLabelOutlineOn').result;
172
- FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::LabelOutlineHelperFunction', ['#ifdef vtkImageLabelOutlineOn', 'vec3 fragCoordToIndexSpace(vec4 fragCoord) {', ' vec4 pcPos = vec4(', ' (fragCoord.x / vpWidth - vpOffsetX - 0.5) * 2.0,', ' (fragCoord.y / vpHeight - vpOffsetY - 0.5) * 2.0,', ' (fragCoord.z - 0.5) * 2.0,', ' 1.0);', '', ' vec4 worldCoord = PCWCMatrix * pcPos;', ' vec4 vertex = (worldCoord/worldCoord.w);', '', ' vec3 index = (vWCtoIDX * vertex).xyz;', '', ' // half voxel fix for labelmapOutline', ' return (index + vec3(0.5)) / vec3(imageDimensions);', '}', '#endif']).result;
172
+ FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::LabelOutlineHelperFunction', ['#ifdef vtkImageLabelOutlineOn', 'vec3 fragCoordToIndexSpace(vec4 fragCoord) {', ' vec4 pcPos = vec4(', ' (fragCoord.x / vpWidth - vpOffsetX - 0.5) * 2.0,', ' (fragCoord.y / vpHeight - vpOffsetY - 0.5) * 2.0,', ' (fragCoord.z - 0.5) * 2.0,', ' 1.0);', '', ' vec4 worldCoord = PCWCMatrix * pcPos;', ' vec4 vertex = (worldCoord/worldCoord.w);', '', ' vec3 index = (vWCtoIDX * vertex).xyz;', '', ' // half voxel fix for labelmapOutline', ' return (index + vec3(0.5)) / vec3(imageDimensions);', '}', 'vec2 getSliceCoords(vec3 coord, int axis) {', ' if (axis == 0) return coord.yz;', ' if (axis == 1) return coord.xz;', ' if (axis == 2) return coord.xy;', '}', '#endif']).result;
173
173
  }
174
174
  if (iComps) {
175
175
  const rgba = ['r', 'g', 'b', 'a'];
@@ -201,7 +201,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
201
201
  FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::TCoord::Impl', [...splitStringOnEnter(`
202
202
  #ifdef vtkImageLabelOutlineOn
203
203
  vec3 centerPosIS = fragCoordToIndexSpace(gl_FragCoord);
204
- float centerValue = texture2D(texture1, centerPosIS.xy).r;
204
+ float centerValue = texture2D(texture1, getSliceCoords(centerPosIS, sliceAxis)).r;
205
205
  bool pixelOnBorder = false;
206
206
  vec3 tColor = texture2D(colorTexture1, vec2(centerValue * cscale0 + cshift0, 0.5)).rgb;
207
207
  float scalarOpacity = texture2D(pwfTexture1, vec2(centerValue * pwfscale0 + pwfshift0, 0.5)).r;
@@ -212,7 +212,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
212
212
  int actualThickness = int(textureValue * 255.0);
213
213
 
214
214
  if (segmentIndex == 0){
215
- gl_FragData[0] = vec4(0.0, 1.0, 1.0, 0.0);
215
+ gl_FragData[0] = vec4(0.0, 0.0, 0.0, 0.0);
216
216
  return;
217
217
  }
218
218
 
@@ -225,7 +225,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
225
225
  gl_FragCoord.y + float(j),
226
226
  gl_FragCoord.z, gl_FragCoord.w);
227
227
  vec3 neighborPosIS = fragCoordToIndexSpace(neighborPixelCoord);
228
- float value = texture2D(texture1, neighborPosIS.xy).r;
228
+ float value = texture2D(texture1, getSliceCoords(neighborPosIS, sliceAxis)).r;
229
229
  if (value != centerValue) {
230
230
  pixelOnBorder = true;
231
231
  break;
@@ -474,7 +474,14 @@ function vtkOpenGLImageMapper(publicAPI, model) {
474
474
  if (vtkImageLabelOutline === true) {
475
475
  const worldToIndex = image.getWorldToIndex();
476
476
  const imageDimensions = image.getDimensions();
477
- program.setUniform3i('imageDimensions', imageDimensions[0], imageDimensions[1], 1);
477
+ let sliceAxis = model.renderable.getClosestIJKAxis().ijkMode;
478
+
479
+ // SlicingMode.NONE equates to SlicingMode.K
480
+ if (sliceAxis === SlicingMode.NONE) {
481
+ sliceAxis = SlicingMode.K;
482
+ }
483
+ program.setUniform3i('imageDimensions', imageDimensions[0], imageDimensions[1], imageDimensions[2]);
484
+ program.setUniformi('sliceAxis', sliceAxis);
478
485
  program.setUniformMatrix('vWCtoIDX', worldToIndex);
479
486
  const labelOutlineKeyMats = model.openGLCamera.getKeyMatrices(ren);
480
487
 
@@ -896,7 +903,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
896
903
  }
897
904
  };
898
905
  publicAPI.updatelabelOutlineThicknessTexture = image => {
899
- const labelOutlineThicknessArray = image.getProperty().getLabelOutlineThickness();
906
+ const labelOutlineThicknessArray = image.getProperty().getLabelOutlineThicknessByReference();
900
907
  const lTex = model._openGLRenderWindow.getGraphicsResourceForObject(labelOutlineThicknessArray);
901
908
 
902
909
  // compute the join of the labelOutlineThicknessArray so that
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Even when the EXT_texture_norm16 extension is present, linear filtering
3
+ * might not be supported for normalized fixed point textures.
4
+ *
5
+ * This is a driver bug. See https://github.com/KhronosGroup/WebGL/issues/3706
6
+ * @return {boolean}
7
+ */
8
+ function supportsNorm16Linear() {
9
+ try {
10
+ const canvasSize = 4;
11
+ const texWidth = 2;
12
+ const texHeight = 1;
13
+ const texData = new Int16Array([0, 2 ** 15 - 1]);
14
+ const pixelToCheck = [1, 1];
15
+ const canvas = document.createElement('canvas');
16
+ canvas.width = canvasSize;
17
+ canvas.height = canvasSize;
18
+ const gl = canvas.getContext('webgl2');
19
+ if (!gl) {
20
+ return false;
21
+ }
22
+ const ext = gl.getExtension('EXT_texture_norm16');
23
+ if (!ext) {
24
+ return false;
25
+ }
26
+ const vs = `#version 300 es
27
+ void main() {
28
+ gl_PointSize = ${canvasSize.toFixed(1)};
29
+ gl_Position = vec4(0, 0, 0, 1);
30
+ }
31
+ `;
32
+ const fs = `#version 300 es
33
+ precision highp float;
34
+ precision highp int;
35
+ precision highp sampler2D;
36
+
37
+ uniform sampler2D u_image;
38
+
39
+ out vec4 color;
40
+
41
+ void main() {
42
+ vec4 intColor = texture(u_image, gl_PointCoord.xy);
43
+ color = vec4(vec3(intColor.rrr), 1);
44
+ }
45
+ `;
46
+ const vertexShader = gl.createShader(gl.VERTEX_SHADER);
47
+ gl.shaderSource(vertexShader, vs);
48
+ gl.compileShader(vertexShader);
49
+ if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
50
+ return false;
51
+ }
52
+ const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
53
+ gl.shaderSource(fragmentShader, fs);
54
+ gl.compileShader(fragmentShader);
55
+ if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
56
+ return false;
57
+ }
58
+ const program = gl.createProgram();
59
+ gl.attachShader(program, vertexShader);
60
+ gl.attachShader(program, fragmentShader);
61
+ gl.linkProgram(program);
62
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
63
+ return false;
64
+ }
65
+ const tex = gl.createTexture();
66
+ gl.bindTexture(gl.TEXTURE_2D, tex);
67
+ gl.texImage2D(gl.TEXTURE_2D, 0, ext.R16_SNORM_EXT, texWidth, texHeight, 0, gl.RED, gl.SHORT, texData);
68
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
69
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
70
+ gl.useProgram(program);
71
+ gl.drawArrays(gl.POINTS, 0, 1);
72
+ const pixel = new Uint8Array(4);
73
+ gl.readPixels(pixelToCheck[0], pixelToCheck[1], 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
74
+ const [r, g, b] = pixel;
75
+ const webglLoseContext = gl.getExtension('WEBGL_lose_context');
76
+ if (webglLoseContext) {
77
+ webglLoseContext.loseContext();
78
+ }
79
+ return r === g && g === b && r !== 0;
80
+ } catch (e) {
81
+ return false;
82
+ }
83
+ }
84
+
85
+ /**
86
+ * @type {boolean | undefined}
87
+ */
88
+ let supportsNorm16LinearCache;
89
+ function supportsNorm16LinearCached() {
90
+ // Only create a canvas+texture+shaders the first time
91
+ if (supportsNorm16LinearCache === undefined) {
92
+ supportsNorm16LinearCache = supportsNorm16Linear();
93
+ }
94
+ return supportsNorm16LinearCache;
95
+ }
96
+
97
+ export { supportsNorm16LinearCached as default };
@@ -5,6 +5,7 @@ import vtkDataArray from '../../Common/Core/DataArray.js';
5
5
  import { V as isPowerOfTwo, R as nearestPowerOfTwo } from '../../Common/Core/Math/index.js';
6
6
  import vtkViewNode from '../SceneGraph/ViewNode.js';
7
7
  import { registerOverride } from './ViewNodeFactory.js';
8
+ import supportsNorm16LinearCached from './Texture/supportsNorm16Linear.js';
8
9
 
9
10
  const {
10
11
  Wrap,
@@ -133,6 +134,12 @@ function vtkOpenGLTexture(publicAPI, model) {
133
134
  publicAPI.activate();
134
135
  }
135
136
  };
137
+ const getNorm16Ext = () => {
138
+ if ((model.minificationFilter === Filter.LINEAR || model.magnificationFilter === Filter.LINEAR) && !supportsNorm16LinearCached()) {
139
+ return undefined;
140
+ }
141
+ return model.oglNorm16Ext;
142
+ };
136
143
 
137
144
  //----------------------------------------------------------------------------
138
145
  publicAPI.destroyTexture = () => {
@@ -285,7 +292,7 @@ function vtkOpenGLTexture(publicAPI, model) {
285
292
  publicAPI.getDefaultInternalFormat = (vtktype, numComps) => {
286
293
  let result = 0;
287
294
  // try default next
288
- result = model._openGLRenderWindow.getDefaultTextureInternalFormat(vtktype, numComps, model.oglNorm16Ext, publicAPI.useHalfFloat());
295
+ result = model._openGLRenderWindow.getDefaultTextureInternalFormat(vtktype, numComps, getNorm16Ext(), publicAPI.useHalfFloat());
289
296
  if (result) {
290
297
  return result;
291
298
  }
@@ -364,9 +371,9 @@ function vtkOpenGLTexture(publicAPI, model) {
364
371
  return model.context.UNSIGNED_BYTE;
365
372
  // prefer norm16 since that is accurate compared to
366
373
  // half float which is not
367
- case model.oglNorm16Ext && !useHalfFloat && VtkDataTypes.SHORT:
374
+ case getNorm16Ext() && !useHalfFloat && VtkDataTypes.SHORT:
368
375
  return model.context.SHORT;
369
- case model.oglNorm16Ext && !useHalfFloat && VtkDataTypes.UNSIGNED_SHORT:
376
+ case getNorm16Ext() && !useHalfFloat && VtkDataTypes.UNSIGNED_SHORT:
370
377
  return model.context.UNSIGNED_SHORT;
371
378
  // use half float type
372
379
  case useHalfFloat && VtkDataTypes.SHORT:
@@ -659,7 +666,7 @@ function vtkOpenGLTexture(publicAPI, model) {
659
666
  }
660
667
  if (model._openGLRenderWindow.getWebgl2()) {
661
668
  const webGLInfo = model._openGLRenderWindow.getGLInformations();
662
- if (webGLInfo.RENDERER.value.match(/WebKit/gi) && navigator.platform.match(/Mac/gi) && model.oglNorm16Ext && (dataType === VtkDataTypes.UNSIGNED_SHORT || dataType === VtkDataTypes.SHORT)) {
669
+ if (webGLInfo.RENDERER.value.match(/WebKit/gi) && navigator.platform.match(/Mac/gi) && getNorm16Ext() && (dataType === VtkDataTypes.UNSIGNED_SHORT || dataType === VtkDataTypes.SHORT)) {
663
670
  // Cannot use texStorage with EXT_texture_norm16 textures on Mac M1 GPU.
664
671
  // No errors reported but the texture is unusable.
665
672
  return false;
@@ -717,7 +724,7 @@ function vtkOpenGLTexture(publicAPI, model) {
717
724
  if (flip) {
718
725
  model.context.pixelStorei(model.context.UNPACK_FLIP_Y_WEBGL, false);
719
726
  }
720
- model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * numComps * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, model.oglNorm16Ext, publicAPI.useHalfFloat());
727
+ model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * numComps * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, getNorm16Ext(), publicAPI.useHalfFloat());
721
728
  publicAPI.deactivate();
722
729
  return true;
723
730
  };
@@ -795,7 +802,7 @@ function vtkOpenGLTexture(publicAPI, model) {
795
802
  h /= 2;
796
803
  }
797
804
  }
798
- model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * numComps * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, model.oglNorm16Ext, publicAPI.useHalfFloat());
805
+ model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * numComps * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, getNorm16Ext(), publicAPI.useHalfFloat());
799
806
  // generateMipmap must not be called here because we manually upload all levels
800
807
  // if it is called, all levels will be overwritten
801
808
 
@@ -845,7 +852,7 @@ function vtkOpenGLTexture(publicAPI, model) {
845
852
  if (model.generateMipmap) {
846
853
  model.context.generateMipmap(model.target);
847
854
  }
848
- model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, model.oglNorm16Ext, publicAPI.useHalfFloat());
855
+ model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, getNorm16Ext(), publicAPI.useHalfFloat());
849
856
  publicAPI.deactivate();
850
857
  return true;
851
858
  };
@@ -895,7 +902,7 @@ function vtkOpenGLTexture(publicAPI, model) {
895
902
  if (model.generateMipmap) {
896
903
  model.context.generateMipmap(model.target);
897
904
  }
898
- model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(VtkDataTypes.UNSIGNED_CHAR, model.oglNorm16Ext, publicAPI.useHalfFloat());
905
+ model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(VtkDataTypes.UNSIGNED_CHAR, getNorm16Ext(), publicAPI.useHalfFloat());
899
906
  publicAPI.deactivate();
900
907
  return true;
901
908
  };
@@ -1013,7 +1020,7 @@ function vtkOpenGLTexture(publicAPI, model) {
1013
1020
  }
1014
1021
 
1015
1022
  // Handle SHORT data type with EXT_texture_norm16 extension
1016
- if (model.oglNorm16Ext && !useHalfFloat && dataType === VtkDataTypes.SHORT) {
1023
+ if (getNorm16Ext() && !useHalfFloat && dataType === VtkDataTypes.SHORT) {
1017
1024
  for (let c = 0; c < numComps; ++c) {
1018
1025
  model.volumeInfo.scale[c] = 32767.0; // Scale to [-1, 1] range
1019
1026
  }
@@ -1022,7 +1029,7 @@ function vtkOpenGLTexture(publicAPI, model) {
1022
1029
  }
1023
1030
 
1024
1031
  // Handle UNSIGNED_SHORT data type with EXT_texture_norm16 extension
1025
- if (model.oglNorm16Ext && !useHalfFloat && dataType === VtkDataTypes.UNSIGNED_SHORT) {
1032
+ if (getNorm16Ext() && !useHalfFloat && dataType === VtkDataTypes.UNSIGNED_SHORT) {
1026
1033
  for (let c = 0; c < numComps; ++c) {
1027
1034
  model.volumeInfo.scale[c] = 65535.0; // Scale to [0, 1] range
1028
1035
  }
@@ -1112,7 +1119,7 @@ function vtkOpenGLTexture(publicAPI, model) {
1112
1119
  if (model.generateMipmap) {
1113
1120
  model.context.generateMipmap(model.target);
1114
1121
  }
1115
- model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(dataTypeToUse, model.oglNorm16Ext, publicAPI.useHalfFloat());
1122
+ model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(dataTypeToUse, getNorm16Ext(), publicAPI.useHalfFloat());
1116
1123
  publicAPI.deactivate();
1117
1124
  return true;
1118
1125
  };
@@ -1,5 +1,6 @@
1
1
  import { m as macro } from '../../../macros2.js';
2
2
  import { k as add } from '../../../Common/Core/Math/index.js';
3
+ import vtkBoundingBox from '../../../Common/DataModel/BoundingBox.js';
3
4
  import vtkPointPicker from '../../../Rendering/Core/PointPicker.js';
4
5
 
5
6
  const MAX_POINTS = 3;
@@ -8,6 +9,7 @@ function widgetBehavior(publicAPI, model) {
8
9
  model._isDragging = false;
9
10
  const picker = vtkPointPicker.newInstance();
10
11
  picker.setPickFromList(1);
12
+ publicAPI.getBounds = () => model.widgetState.getHandleList().reduce((bounds, handle) => vtkBoundingBox.inflate(vtkBoundingBox.addPoint(bounds, ...handle.getOrigin()), publicAPI.getScaleInPixels() ? 0 : handle.getScale1() / 2), [...vtkBoundingBox.INIT_BOUNDS]);
11
13
 
12
14
  // --------------------------------------------------------------------------
13
15
  // Display 2D
@@ -2,7 +2,7 @@ import { m as macro } from '../../macros2.js';
2
2
  import vtkAbstractWidgetFactory from '../Core/AbstractWidgetFactory.js';
3
3
  import vtkConvexFaceContextRepresentation from '../Representations/ConvexFaceContextRepresentation.js';
4
4
  import widgetBehavior from './InteractiveOrientationWidget/behavior.js';
5
- import { generateState, INITIAL_POINTS } from './InteractiveOrientationWidget/state.js';
5
+ import { INITIAL_POINTS, generateState } from './InteractiveOrientationWidget/state.js';
6
6
  import { Behavior } from '../Representations/WidgetRepresentation/Constants.js';
7
7
  import { ViewTypes } from '../Core/WidgetManager/Constants.js';
8
8