@kitware/vtk.js 28.6.0 → 28.8.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.
@@ -490,8 +490,19 @@ function vtkDataArray(publicAPI, model) {
490
490
  };
491
491
 
492
492
  publicAPI.deepCopy = function (other) {
493
- publicAPI.shallowCopy(other);
494
- publicAPI.setData(other.getData().slice());
493
+ // Retain current dataType and array reference before shallowCopy call.
494
+ var currentType = publicAPI.getDataType();
495
+ var currentArray = model.values;
496
+ publicAPI.shallowCopy(other); // Avoid array reallocation if size already sufficient
497
+ // and dataTypes match.
498
+
499
+ if ((currentArray === null || currentArray === void 0 ? void 0 : currentArray.length) >= other.getNumberOfValues() && currentType === other.getDataType()) {
500
+ currentArray.set(other.getData());
501
+ model.values = currentArray;
502
+ publicAPI.dataChange();
503
+ } else {
504
+ publicAPI.setData(other.getData().slice());
505
+ }
495
506
  };
496
507
 
497
508
  publicAPI.interpolateTuple = function (idx, source1, source1Idx, source2, source2Idx, t) {
@@ -1,5 +1,5 @@
1
- import { quat } from 'gl-matrix';
2
- import { Vector2, Vector3 } from './../../types';
1
+ import { quat, vec3 } from 'gl-matrix';
2
+ import { Nullable, Vector2, Vector3 } from './../../types';
3
3
  import vtkCell, { ICellInitialValues } from './Cell';
4
4
  import { IIntersectWithLine } from './Line';
5
5
 
@@ -67,6 +67,31 @@ export interface vtkPolyLine extends vtkCell {
67
67
  * @param distance The distance from the first point of the polyline
68
68
  */
69
69
  findPointIdAtDistanceFromFirstPoint(distance: number): number;
70
+
71
+ /**
72
+ * An array of quaternions used to orient the polyline at each of its point
73
+ * The length of the array has to be the same size as the number of points
74
+ * Defaults to null.
75
+ */
76
+ getOrientations(): Nullable<quat[]>;
77
+
78
+ /**
79
+ * @see getOrientations
80
+ * @param orientations
81
+ */
82
+ setOrientations(orientations: Nullable<quat[]>): boolean;
83
+
84
+ /**
85
+ * The function used in getDistancesToFirstPoint and in findPointIdAtDistanceFromFirstPoint
86
+ * Defaults to vec3.dist of gl-matrix
87
+ */
88
+ getDistanceFunction(): (a: vec3, b: vec3) => number;
89
+
90
+ /**
91
+ * @see getDistanceFunction
92
+ * @param f
93
+ */
94
+ setDistanceFunction(f: (a: vec3, b: vec3) => number): boolean;
70
95
  }
71
96
 
72
97
  /**
@@ -58,7 +58,9 @@ function vtkPolyLine(publicAPI, model) {
58
58
  };
59
59
 
60
60
  publicAPI.getDistancesToFirstPoint = function () {
61
- if (model.distancesTime.getMTime() < model.points.getMTime()) {
61
+ var dTime = model.distancesTime.getMTime();
62
+
63
+ if (dTime < model.points.getMTime() || dTime < publicAPI.getMTime()) {
62
64
  var numPoints = publicAPI.getNumberOfPoints();
63
65
 
64
66
  if (!model.distances) {
@@ -76,7 +78,7 @@ function vtkPolyLine(publicAPI, model) {
76
78
 
77
79
  for (var i = 1; i < numPoints; ++i) {
78
80
  model.points.getPoint(i, currentPoint);
79
- totalDistance += vec3.dist(previousPoint, currentPoint);
81
+ totalDistance += model.distanceFunction(previousPoint, currentPoint);
80
82
  model.distances[i] = totalDistance;
81
83
  vec3.copy(previousPoint, currentPoint);
82
84
  }
@@ -121,15 +123,16 @@ function vtkPolyLine(publicAPI, model) {
121
123
 
122
124
 
123
125
  var DEFAULT_VALUES = {
124
- orientations: null // an array of quat or null
125
-
126
+ orientations: null,
127
+ // an array of quat or null
128
+ distanceFunction: vec3.dist
126
129
  }; // ----------------------------------------------------------------------------
127
130
 
128
131
  function extend(publicAPI, model) {
129
132
  var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
130
133
  Object.assign(model, DEFAULT_VALUES, initialValues);
131
134
  vtkCell.extend(publicAPI, model, initialValues);
132
- macro.setGet(publicAPI, model, ['orientations']);
135
+ macro.setGet(publicAPI, model, ['orientations', 'distanceFunction']);
133
136
  model.distancesTime = {};
134
137
  macro.obj(model.distancesTime, {
135
138
  mtime: 0
@@ -0,0 +1,77 @@
1
+ import { vtkAlgorithm, vtkObject } from './../../interfaces';
2
+ import vtkImageData from './../../Common/DataModel/ImageData';
3
+ import vtkPolyData from './../../Common/DataModel/PolyData';
4
+
5
+ export const LINE_ARRAY: number[];
6
+
7
+ export interface IImageDataOutlineFilterInitialValues {
8
+ }
9
+
10
+ type vtkImageDataOutlineFilterBase = vtkObject & vtkAlgorithm;
11
+
12
+ export interface vtkImageDataOutlineFilter extends vtkImageDataOutlineFilterBase {
13
+ /**
14
+ *
15
+ * @param inData
16
+ * @param outData
17
+ */
18
+ requestData(inData: vtkImageData, outData: vtkPolyData): void;
19
+
20
+ /**
21
+ * Flag that indicates whether the output will generate faces of the outline.
22
+ * @returns {boolean}
23
+ */
24
+ getGenerateFaces(): boolean;
25
+
26
+ /**
27
+ * Flag that indicates whether the output will generate wireframe lines of the outline.
28
+ * @returns {boolean}
29
+ */
30
+ getGenerateLines(): boolean;
31
+
32
+ /**
33
+ * Flag to indicate that the output should generate wireframe of the outline.
34
+ * @param {boolean} generateLines
35
+ */
36
+ setGenerateLines(generateLines: boolean): boolean;
37
+
38
+ /**
39
+ * Flag to indicate that the output should generate triangulated faces of the outline.
40
+ * @param {boolean} generateFaces
41
+ */
42
+ setGenerateFaces(generateFaces: boolean): boolean;
43
+
44
+ }
45
+
46
+ /**
47
+ * Method used to decorate a given object (publicAPI+model) with
48
+ * vtkImageDataOutlineFilter characteristics.
49
+ *
50
+ * @param publicAPI object on which methods will be bounds (public)
51
+ * @param model object on which data structure will be bounds (protected)
52
+ * @param {IImageDataOutlineFilterInitialValues} [initialValues] (default: {})
53
+ */
54
+ export function extend(publicAPI: object, model: object, initialValues?: IImageDataOutlineFilterInitialValues): void;
55
+
56
+ /**
57
+ * Method used to create a new instance of vtkImageDataOutlineFilter
58
+ * @param {IImageDataOutlineFilterInitialValues} [initialValues] for pre-setting some of its content
59
+ */
60
+ export function newInstance(initialValues?: IImageDataOutlineFilterInitialValues): vtkImageDataOutlineFilter;
61
+
62
+
63
+ /**
64
+ * vtkImageDataOutlineFilter - A filter that generates oriented outline for
65
+ * vtkImageData.
66
+ *
67
+ * vtkImageDataOutlineFilter is a filter that generates a wireframe or
68
+ * triangulated rectangular-cuboid as an outline of an input vtkImageData.
69
+ * It takes into account the orientation / DirectionMatrix of the image, so the
70
+ * output outline may not be axes aligned.
71
+ *
72
+ */
73
+ export declare const vtkImageDataOutlineFilter: {
74
+ newInstance: typeof newInstance;
75
+ extend: typeof extend;
76
+ }
77
+ export default vtkImageDataOutlineFilter;
@@ -0,0 +1,82 @@
1
+ import macro from '../../macros.js';
2
+ import vtkCubeSource from '../Sources/CubeSource.js';
3
+
4
+ var vtkErrorMacro = macro.vtkErrorMacro; // ----------------------------------------------------------------------------
5
+ // vtkImageDataOutlineFilter methods
6
+ // ----------------------------------------------------------------------------
7
+
8
+ function vtkImageDataOutlineFilter(publicAPI, model) {
9
+ // Set our className
10
+ model.classHierarchy.push('vtkImageDataOutlineFilter');
11
+
12
+ publicAPI.requestData = function (inData, outData) {
13
+ // implement requestData
14
+ var input = inData[0];
15
+
16
+ if (!input || !input.isA('vtkImageData')) {
17
+ vtkErrorMacro('Invalid or missing input');
18
+ return;
19
+ } // First create a cube polydata in the index-space of the image.
20
+ // The benefit of using `getSpatialExtent` call is that it automatically
21
+ // takes care of 0.5 voxel padding as required by an vtkImageData representation.
22
+
23
+
24
+ var spatialExt = input.getSpatialExtent();
25
+
26
+ if (!spatialExt) {
27
+ vtkErrorMacro('Unable to fetch spatial extents of input image.');
28
+ return;
29
+ }
30
+
31
+ model._cubeSource.setBounds(spatialExt); // Then apply index-to-world transform to the cube to create the outline.
32
+
33
+
34
+ model._cubeSource.setMatrix(input.getIndexToWorld());
35
+
36
+ outData[0] = model._cubeSource.getOutputData();
37
+ }; // Forward calls for [set/get]Generate[Faces/Lines] functions to cubeSource:
38
+
39
+
40
+ publicAPI.setGenerateFaces = function (generateFaces) {
41
+ if (model._cubeSource.setGenerateFaces(generateFaces)) {
42
+ publicAPI.modified();
43
+ }
44
+ };
45
+
46
+ publicAPI.setGenerateLines = function (generateLines) {
47
+ if (model._cubeSource.setGenerateLines(generateLines)) {
48
+ publicAPI.modified();
49
+ }
50
+ };
51
+
52
+ publicAPI.getGenerateFaces = model._cubeSource.getGenerateFaces;
53
+ publicAPI.getGenerateLines = model._cubeSource.getGenerateLines;
54
+ } // ----------------------------------------------------------------------------
55
+ // Object factory
56
+ // ----------------------------------------------------------------------------
57
+
58
+
59
+ var DEFAULT_VALUES = {}; // ----------------------------------------------------------------------------
60
+
61
+ function extend(publicAPI, model) {
62
+ var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
63
+ Object.assign(model, DEFAULT_VALUES, initialValues); // Make this a VTK object
64
+
65
+ macro.obj(publicAPI, model); // Also make it an algorithm with one input and one output
66
+
67
+ macro.algo(publicAPI, model, 1, 1); // Internal persistent objects
68
+
69
+ model._cubeSource = vtkCubeSource.newInstance();
70
+ macro.moveToProtected(publicAPI, model, ['cubeSource', 'tmpOut']); // Object specific methods
71
+
72
+ vtkImageDataOutlineFilter(publicAPI, model);
73
+ } // ----------------------------------------------------------------------------
74
+
75
+ var newInstance = macro.newInstance(extend, 'vtkImageDataOutlineFilter'); // ----------------------------------------------------------------------------
76
+
77
+ var vtkImageDataOutlineFilter$1 = {
78
+ newInstance: newInstance,
79
+ extend: extend
80
+ };
81
+
82
+ export { vtkImageDataOutlineFilter$1 as default, extend, newInstance };
@@ -1,3 +1,4 @@
1
+ import { mat4 } from 'gl-matrix';
1
2
  import { vtkAlgorithm, vtkObject } from './../../interfaces';
2
3
  import { Bounds, Vector3 } from './../../types';
3
4
 
@@ -41,6 +42,24 @@ export interface vtkCubeSource extends vtkCubeSourceBase {
41
42
  */
42
43
  getGenerate3DTextureCoordinates(): boolean;
43
44
 
45
+ /**
46
+ * Flag that indicates whether the output will generate faces of the outline.
47
+ * @returns {boolean}
48
+ */
49
+ getGenerateFaces(): boolean;
50
+
51
+ /**
52
+ * Flag that indicates whether the output will generate wireframe lines of the outline.
53
+ * @returns {boolean}
54
+ */
55
+ getGenerateLines(): boolean;
56
+
57
+ /**
58
+ * Get the 4x4 transformation set to apply as a final trasformation to the output.
59
+ * @param matrix
60
+ */
61
+ getMatrix(): mat4;
62
+
44
63
  /**
45
64
  *
46
65
  * @default [0.0, 0.0, 0.0]
@@ -117,6 +136,24 @@ export interface vtkCubeSource extends vtkCubeSourceBase {
117
136
  */
118
137
  setGenerate3DTextureCoordinates(generate3DTextureCoordinates: boolean): boolean;
119
138
 
139
+ /**
140
+ * Flag to indicate that the output should generate wireframe of the outline.
141
+ * @param {boolean} generateLines
142
+ */
143
+ setGenerateLines(generateLines: boolean): boolean;
144
+
145
+ /**
146
+ * Flag to indicate that the output should generate triangulated faces of the outline.
147
+ * @param {boolean} generateFaces
148
+ */
149
+ setGenerateFaces(generateFaces: boolean): boolean;
150
+
151
+ /**
152
+ * Set a 4x4 transformation that will be applied as a final trasformation to the output.
153
+ * @param matrix
154
+ */
155
+ setMatrix(matrix: mat4): boolean;
156
+
120
157
  /**
121
158
  * Float array of size 3 representing the angles, in degrees, of rotation for the cube.
122
159
  * @param xAngle
@@ -1,9 +1,14 @@
1
1
  import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
2
2
  import macro from '../../macros.js';
3
+ import vtkCellArray from '../../Common/Core/CellArray.js';
3
4
  import vtkDataArray from '../../Common/Core/DataArray.js';
5
+ import { IDENTITY } from '../../Common/Core/Math/Constants.js';
4
6
  import vtkPolyData from '../../Common/DataModel/PolyData.js';
5
7
  import vtkMatrixBuilder from '../../Common/Core/MatrixBuilder.js';
6
8
 
9
+ var LINE_ARRAY = [2, 0, 1, 2, 2, 3, 2, 4, 5, 2, 6, 7, 2, 0, 2, 2, 1, 3, 2, 4, 6, 2, 5, 7, 2, 0, 4, 2, 1, 5, 2, 2, 6, 2, 3, 7]; // prettier-ignore
10
+
11
+ var POLY_ARRAY = [4, 0, 1, 3, 2, 4, 4, 6, 7, 5, 4, 8, 10, 11, 9, 4, 12, 13, 15, 14, 4, 16, 18, 19, 17, 4, 20, 21, 23, 22]; // ----------------------------------------------------------------------------
7
12
  // vtkCubeSource methods
8
13
  // ----------------------------------------------------------------------------
9
14
 
@@ -20,7 +25,6 @@ function vtkCubeSource(publicAPI, model) {
20
25
 
21
26
  var polyData = vtkPolyData.newInstance();
22
27
  outData[0] = polyData;
23
- var numberOfPolys = 6;
24
28
  var numberOfPoints = 24; // Define points
25
29
 
26
30
  var points = macro.newTypedArray(model.pointType, numberOfPoints * 3);
@@ -175,42 +179,29 @@ function vtkCubeSource(publicAPI, model) {
175
179
 
176
180
  vtkMatrixBuilder.buildFromDegree().rotateX(model.rotations[0]).rotateY(model.rotations[1]).rotateZ(model.rotations[2]).apply(points).apply(normals); // Apply transformation to the points coordinates
177
181
 
178
- (_vtkMatrixBuilder$bui = vtkMatrixBuilder.buildFromRadian()).translate.apply(_vtkMatrixBuilder$bui, _toConsumableArray(model.center)).apply(points); // Define quads
179
-
180
-
181
- var polys = new Uint16Array(numberOfPolys * 5);
182
- polyData.getPolys().setData(polys, 1);
183
- var polyIndex = 0;
184
- polys[polyIndex++] = 4;
185
- polys[polyIndex++] = 0;
186
- polys[polyIndex++] = 1;
187
- polys[polyIndex++] = 3;
188
- polys[polyIndex++] = 2;
189
- polys[polyIndex++] = 4;
190
- polys[polyIndex++] = 4;
191
- polys[polyIndex++] = 6;
192
- polys[polyIndex++] = 7;
193
- polys[polyIndex++] = 5;
194
- polys[polyIndex++] = 4;
195
- polys[polyIndex++] = 8;
196
- polys[polyIndex++] = 10;
197
- polys[polyIndex++] = 11;
198
- polys[polyIndex++] = 9;
199
- polys[polyIndex++] = 4;
200
- polys[polyIndex++] = 12;
201
- polys[polyIndex++] = 13;
202
- polys[polyIndex++] = 15;
203
- polys[polyIndex++] = 14;
204
- polys[polyIndex++] = 4;
205
- polys[polyIndex++] = 16;
206
- polys[polyIndex++] = 18;
207
- polys[polyIndex++] = 19;
208
- polys[polyIndex++] = 17;
209
- polys[polyIndex++] = 4;
210
- polys[polyIndex++] = 20;
211
- polys[polyIndex++] = 21;
212
- polys[polyIndex++] = 23;
213
- polys[polyIndex] = 22;
182
+ (_vtkMatrixBuilder$bui = vtkMatrixBuilder.buildFromRadian()).translate.apply(_vtkMatrixBuilder$bui, _toConsumableArray(model.center)).apply(points); // Apply optional additionally specified matrix transformation
183
+
184
+
185
+ vtkMatrixBuilder.buildFromRadian().setMatrix(model.matrix).apply(points); // prettier-ignore
186
+
187
+ var rotMatrix = [model.matrix[0], model.matrix[1], model.matrix[2], 0, model.matrix[4], model.matrix[5], model.matrix[6], 0, model.matrix[8], model.matrix[9], model.matrix[10], 0, 0, 0, 0, 1];
188
+ vtkMatrixBuilder.buildFromRadian().setMatrix(rotMatrix).apply(normals); // Lastly, generate the necessary cell arrays.
189
+
190
+ if (model.generateFaces) {
191
+ polyData.getPolys().deepCopy(model._polys);
192
+ } else {
193
+ polyData.getPolys().initialize();
194
+ }
195
+
196
+ if (model.generateLines) {
197
+ polyData.getLines().deepCopy(model._lineCells); // only set normals for faces, not for lines.
198
+
199
+ polyData.getPointData().setNormals(null);
200
+ } else {
201
+ polyData.getLines().initialize();
202
+ }
203
+
204
+ polyData.modified();
214
205
  }
215
206
 
216
207
  publicAPI.setBounds = function () {
@@ -228,10 +219,10 @@ function vtkCubeSource(publicAPI, model) {
228
219
  return;
229
220
  }
230
221
 
231
- model.xLength = boundsArray[1] - boundsArray[0];
232
- model.yLength = boundsArray[3] - boundsArray[2];
233
- model.zLength = boundsArray[5] - boundsArray[4];
234
- model.center = [(boundsArray[0] + boundsArray[1]) / 2.0, (boundsArray[2] + boundsArray[3]) / 2.0, (boundsArray[4] + boundsArray[5]) / 2.0];
222
+ publicAPI.setXLength(boundsArray[1] - boundsArray[0]);
223
+ publicAPI.setYLength(boundsArray[3] - boundsArray[2]);
224
+ publicAPI.setZLength(boundsArray[5] - boundsArray[4]);
225
+ publicAPI.setCenter([(boundsArray[0] + boundsArray[1]) / 2.0, (boundsArray[2] + boundsArray[3]) / 2.0, (boundsArray[4] + boundsArray[5]) / 2.0]);
235
226
  }; // Expose methods
236
227
 
237
228
 
@@ -247,8 +238,11 @@ var DEFAULT_VALUES = {
247
238
  zLength: 1.0,
248
239
  center: [0.0, 0.0, 0.0],
249
240
  rotations: [0.0, 0.0, 0.0],
241
+ matrix: _toConsumableArray(IDENTITY),
250
242
  pointType: 'Float64Array',
251
- generate3DTextureCoordinates: false
243
+ generate3DTextureCoordinates: false,
244
+ generateFaces: true,
245
+ generateLines: false
252
246
  }; // ----------------------------------------------------------------------------
253
247
 
254
248
  function extend(publicAPI, model) {
@@ -256,8 +250,17 @@ function extend(publicAPI, model) {
256
250
  Object.assign(model, DEFAULT_VALUES, initialValues); // Build VTK API
257
251
 
258
252
  macro.obj(publicAPI, model);
259
- macro.setGet(publicAPI, model, ['xLength', 'yLength', 'zLength', 'generate3DTextureCoordinates']);
253
+ macro.setGet(publicAPI, model, ['xLength', 'yLength', 'zLength', 'generate3DTextureCoordinates', 'generateFaces', 'generateLines']);
260
254
  macro.setGetArray(publicAPI, model, ['center', 'rotations'], 3);
255
+ macro.setGetArray(publicAPI, model, ['matrix'], 16); // Internal persistent/static objects
256
+
257
+ model._polys = vtkCellArray.newInstance({
258
+ values: Uint16Array.from(POLY_ARRAY)
259
+ });
260
+ model._lineCells = vtkCellArray.newInstance({
261
+ values: Uint16Array.from(LINE_ARRAY)
262
+ });
263
+ macro.moveToProtected(publicAPI, model, ['polys', 'lineCells']);
261
264
  macro.algo(publicAPI, model, 0, 1);
262
265
  vtkCubeSource(publicAPI, model);
263
266
  } // ----------------------------------------------------------------------------
@@ -62,6 +62,21 @@ export interface vtkImageCPRMapper extends vtkAbstractMapper3D {
62
62
  */
63
63
  setUseUniformOrientation(useUniformOrientation: boolean): boolean;
64
64
 
65
+ /**
66
+ * A point used to offset each line of pixel in the rendering
67
+ * The line of pixel is offseted such as the center of the line is as close as possible to the center point
68
+ * This can be used in combination with @see getUseUniformOrientation and a custom distance function for @see getOrientedCenterline to visualize a CPR in projected mode or stretched mode
69
+ * Defaults to null.
70
+ * @returns the center point
71
+ */
72
+ getCenterPoint(): Nullable<vec3>;
73
+
74
+ /**
75
+ * @see getCenterPoint
76
+ * @param point
77
+ */
78
+ setCenterPoint(point: Nullable<vec3>): boolean;
79
+
65
80
  /**
66
81
  * This flag indicates wether the GPU should use half float or not
67
82
  * When true, will use half float
@@ -191,6 +206,17 @@ export interface vtkImageCPRMapper extends vtkAbstractMapper3D {
191
206
  */
192
207
  preRenderCheck(): boolean;
193
208
 
209
+ /**
210
+ * Configure the mapper and the centerline to be in straightened CPR mode
211
+ */
212
+ useStraightenedMode(): void;
213
+
214
+ /**
215
+ * Configure the mapper and the centerline to be in strectched CPR mode
216
+ * @param centerPoint The center point, optional, default to the first point of the centerline or [0, 0, 0]
217
+ */
218
+ useStretchedMode(centerPoint?: Nullable<vec3>): void;
219
+
194
220
  /**
195
221
  * Set the polydata used as a centerline
196
222
  * You can also use `publicAPI.setInputData(centerlineData, 1);`
@@ -346,7 +372,10 @@ export function newInstance(initialValues?: IImageCPRMapperInitialValues): vtkIm
346
372
 
347
373
  /**
348
374
  * CPR in vtkImageCPRMapper stands for Curved Planar Reformation. This mapper
349
- * can be used to visualize tubular structures such as blood vessels.
375
+ * can be used to visualize tubular structures such as blood vessels. It can be
376
+ * used in projected mode, stretched mode or straightened mode depending on the
377
+ * settings @see getUseUniformOrientation , @see getCenterPoint and the distance
378
+ * function of @see getOrientedCenterline .
350
379
  *
351
380
  * This specialised mapper takes as input a vtkImageData representing a volume
352
381
  * ( @see setImageData ) and a vtkPolyData representing a centerline
@@ -293,6 +293,36 @@ function vtkImageCPRMapper(publicAPI, model) {
293
293
  return true;
294
294
  };
295
295
 
296
+ publicAPI.useStraightenedMode = function () {
297
+ publicAPI.setCenterPoint(null);
298
+ publicAPI.setUseUniformOrientation(false);
299
+ publicAPI.getOrientedCenterline().setDistanceFunction(vec3.dist);
300
+ };
301
+
302
+ publicAPI.useStretchedMode = function (centerPoint) {
303
+ var centerline = publicAPI.getOrientedCenterline(); // Set center point
304
+
305
+ if (!centerPoint) {
306
+ // Get the first point of the centerline if there is one
307
+ var centerlinePoints = centerline.getPoints();
308
+ var newCenterPoint = centerlinePoints.getNumberOfTuples() > 0 ? centerlinePoints.getPoint(0) : [0, 0, 0];
309
+ publicAPI.setCenterPoint(newCenterPoint);
310
+ } else {
311
+ publicAPI.setCenterPoint(centerPoint);
312
+ } // Enable uniform orientation
313
+
314
+
315
+ publicAPI.setUseUniformOrientation(true); // Change distance function
316
+
317
+ centerline.setDistanceFunction(function (a, b) {
318
+ var direction = publicAPI.getUniformDirection();
319
+ var vec = vec3.subtract([], a, b);
320
+ var d2 = vec3.squaredLength(vec);
321
+ var x = vec3.dot(direction, vec);
322
+ return Math.sqrt(d2 - x * x);
323
+ });
324
+ };
325
+
296
326
  publicAPI.setCenterlineData = function (centerlineData) {
297
327
  return publicAPI.setInputData(centerlineData, 1);
298
328
  };
@@ -326,6 +356,7 @@ var DEFAULT_VALUES = {
326
356
  width: 10,
327
357
  uniformOrientation: [0, 0, 0, 1],
328
358
  useUniformOrientation: false,
359
+ centerPoint: null,
329
360
  preferSizeOverAccuracy: false,
330
361
  orientationArrayName: null,
331
362
  tangentDirection: [1, 0, 0],
@@ -345,7 +376,7 @@ function extend(publicAPI, model) {
345
376
  mtime: 0
346
377
  }); // Setters and getters
347
378
 
348
- macro.setGet(publicAPI, model, ['width', 'uniformOrientation', 'useUniformOrientation', 'preferSizeOverAccuracy', 'orientationArrayName', 'tangentDirection', 'bitangentDirection', 'normalDirection']);
379
+ macro.setGet(publicAPI, model, ['width', 'uniformOrientation', 'useUniformOrientation', 'centerPoint', 'preferSizeOverAccuracy', 'orientationArrayName', 'tangentDirection', 'bitangentDirection', 'normalDirection']);
349
380
  CoincidentTopologyHelper.implementCoincidentTopologyMethods(publicAPI, model); // Object methods
350
381
 
351
382
  vtkImageCPRMapper(publicAPI, model);
@@ -449,14 +449,20 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
449
449
  publicAPI.getNeedToRebuildShaders = function (cellBO, ren, actor) {
450
450
  // has something changed that would require us to recreate the shader?
451
451
  // candidates are
452
+ // presence of centerPoint
453
+ // value of useUniformOrientation
452
454
  // property modified (representation interpolation and lighting)
453
455
  // input modified
454
456
  // light complexity changed
455
457
  // render pass shader replacement changed
456
458
  var tNumComp = model.volumeTexture.getComponents();
457
459
  var iComp = actor.getProperty().getIndependentComponents();
460
+ var useCenterPoint = !!model.renderable.getCenterPoint();
461
+ var useUniformOrientation = model.renderable.getUseUniformOrientation();
458
462
 
459
- if (model.lastHaveSeenDepthRequest !== model.haveSeenDepthRequest || cellBO.getProgram() === 0 || model.lastTextureComponents !== tNumComp || model.lastIndependentComponents !== iComp) {
463
+ if (cellBO.getProgram() === 0 || model.lastUseCenterPoint !== useCenterPoint || model.lastUseUniformOrientation !== useUniformOrientation || model.lastHaveSeenDepthRequest !== model.haveSeenDepthRequest || model.lastTextureComponents !== tNumComp || model.lastIndependentComponents !== iComp) {
464
+ model.lastUseCenterPoint = useCenterPoint;
465
+ model.lastUseUniformOrientation = useUniformOrientation;
460
466
  model.lastHaveSeenDepthRequest = model.haveSeenDepthRequest;
461
467
  model.lastTextureComponents = tNumComp;
462
468
  model.lastIndependentComponents = iComp;
@@ -521,6 +527,12 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
521
527
  tcoordFSDec.push('in vec3 centerlineTopDirVSOutput;', 'in vec3 centerlineBotDirVSOutput;', 'in float centerlineAngleVSOutput;');
522
528
  }
523
529
 
530
+ var centerPoint = model.renderable.getCenterPoint();
531
+
532
+ if (centerPoint) {
533
+ tcoordFSDec.push('uniform vec3 globalCenterPoint;');
534
+ }
535
+
524
536
  if (iComps) {
525
537
  for (var comp = 1; comp < tNumComp; comp++) {
526
538
  tcoordFSDec = tcoordFSDec.concat([// color shift and scale
@@ -566,7 +578,13 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
566
578
  tcoordFSImpl.push('vec3 interpolatedCenterlineDir;', 'if (centerlineAngleVSOutput < 0.0) {', ' // Lerp', ' interpolatedCenterlineDir = quadOffsetVSOutput.y * centerlineTopDirVSOutput + (1.0 - quadOffsetVSOutput.y) * centerlineBotDirVSOutput;', '} else {', ' // Slerp', ' float topInterpolationAngle = quadOffsetVSOutput.y * centerlineAngleVSOutput;', ' float botInterpolationAngle = centerlineAngleVSOutput - topInterpolationAngle;', ' interpolatedCenterlineDir = sin(topInterpolationAngle) * centerlineTopDirVSOutput + sin(botInterpolationAngle) * centerlineBotDirVSOutput;', '}', '// Slerp should give a normalized vector but when sin(angle) is small, rounding error occurs', '// Normalize for both lerp and slerp', 'interpolatedCenterlineDir = normalize(interpolatedCenterlineDir);');
567
579
  }
568
580
 
569
- tcoordFSImpl.push('vec3 volumePosMC = centerlinePosVSOutput + quadOffsetVSOutput.x * interpolatedCenterlineDir;', 'vec3 volumePosTC = (MCTCMatrix * vec4(volumePosMC, 1.0)).xyz;', 'if (any(lessThan(volumePosTC, vec3(0.0))) || any(greaterThan(volumePosTC, vec3(1.0))))', '{', ' // set the background color and exit', ' gl_FragData[0] = backgroundColor;', ' return;', '}', 'vec4 tvalue = texture(volumeTexture, volumePosTC);');
581
+ if (centerPoint) {
582
+ tcoordFSImpl.push('float baseOffset = dot(interpolatedCenterlineDir, globalCenterPoint - centerlinePosVSOutput);', 'float horizontalOffset = quadOffsetVSOutput.x + baseOffset;');
583
+ } else {
584
+ tcoordFSImpl.push('float horizontalOffset = quadOffsetVSOutput.x;');
585
+ }
586
+
587
+ tcoordFSImpl.push('vec3 volumePosMC = centerlinePosVSOutput + horizontalOffset * interpolatedCenterlineDir;', 'vec3 volumePosTC = (MCTCMatrix * vec4(volumePosMC, 1.0)).xyz;', 'if (any(lessThan(volumePosTC, vec3(0.0))) || any(greaterThan(volumePosTC, vec3(1.0))))', '{', ' // set the background color and exit', ' gl_FragData[0] = backgroundColor;', ' return;', '}', 'vec4 tvalue = texture(volumeTexture, volumePosTC);');
570
588
 
571
589
  if (iComps) {
572
590
  var rgba = ['r', 'g', 'b', 'a'];
@@ -685,6 +703,11 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
685
703
  if (cellBO.getProgram().isUniformUsed('centerlineDirection')) {
686
704
  var uniformDirection = model.renderable.getUniformDirection();
687
705
  cellBO.getProgram().setUniform3fArray('centerlineDirection', uniformDirection);
706
+ }
707
+
708
+ if (cellBO.getProgram().isUniformUsed('globalCenterPoint')) {
709
+ var centerPoint = model.renderable.getCenterPoint();
710
+ cellBO.getProgram().setUniform3fArray('globalCenterPoint', centerPoint);
688
711
  } // Model coordinates to image space
689
712
  // getWorldToIndex is badly named and is in fact modelToIndex
690
713
  // MCIC -> Model coordinates to index coordinates
@@ -3,16 +3,17 @@ import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
3
3
  import { newInstance as newInstance$1, obj, get, vtkErrorMacro as vtkErrorMacro$1 } from '../../macros.js';
4
4
  import { mat4, mat3, vec3 } from 'gl-matrix';
5
5
  import vtkClosedPolyLineToSurfaceFilter from '../../Filters/General/ClosedPolyLineToSurfaceFilter.js';
6
- import vtkCubeSource from '../../Filters/Sources/CubeSource.js';
7
6
  import vtkCutter from '../../Filters/Core/Cutter.js';
8
7
  import vtkDataArray from '../../Common/Core/DataArray.js';
9
8
  import vtkHelper from './Helper.js';
9
+ import vtkImageDataOutlineFilter from '../../Filters/General/ImageDataOutlineFilter.js';
10
10
  import { f as vtkMath } from '../../Common/Core/Math/index.js';
11
11
  import vtkOpenGLTexture from './Texture.js';
12
12
  import vtkPlane from '../../Common/DataModel/Plane.js';
13
13
  import vtkPolyData from '../../Common/DataModel/PolyData.js';
14
14
  import vtkReplacementShaderMapper from './ReplacementShaderMapper.js';
15
15
  import vtkShaderProgram from './ShaderProgram.js';
16
+ import vtkTransform from '../../Common/Transform/Transform.js';
16
17
  import vtkViewNode from '../SceneGraph/ViewNode.js';
17
18
  import { v as vtkImageResliceMapperVS } from './glsl/vtkImageResliceMapperVS.glsl.js';
18
19
  import { v as vtkImageResliceMapperFS } from './glsl/vtkImageResliceMapperFS.glsl.js';
@@ -789,49 +790,6 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
789
790
  return [false, 2];
790
791
  }
791
792
 
792
- function transformPoints(points, transform) {
793
- var tmp = [0, 0, 0];
794
-
795
- for (var i = 0; i < points.length; i += 3) {
796
- var p = points.subarray(i, i + 3);
797
-
798
- if (transform.length === 9) {
799
- vec3.transformMat3(tmp, p, transform);
800
- } else {
801
- vec3.transformMat4(tmp, p, transform);
802
- }
803
-
804
- p[0] = tmp[0];
805
- p[1] = tmp[1];
806
- p[2] = tmp[2];
807
- }
808
- }
809
-
810
- function imageToCubePolyData(image, outPD) {
811
- // First create a cube polydata in the index-space of the image.
812
- var sext = image === null || image === void 0 ? void 0 : image.getSpatialExtent();
813
-
814
- if (sext) {
815
- model.cubeSource.setXLength(sext[1] - sext[0]);
816
- model.cubeSource.setYLength(sext[3] - sext[2]);
817
- model.cubeSource.setZLength(sext[5] - sext[4]);
818
- } else {
819
- model.cubeSource.setXLength(1);
820
- model.cubeSource.setYLength(1);
821
- model.cubeSource.setZLength(1);
822
- }
823
-
824
- model.cubeSource.setCenter(model.cubeSource.getXLength() / 2.0, model.cubeSource.getYLength() / 2.0, model.cubeSource.getZLength() / 2.0);
825
- model.cubeSource.update();
826
- var out = model.cubeSource.getOutputData();
827
- outPD.getPoints().setData(Float32Array.from(out.getPoints().getData()), 3);
828
- outPD.getPolys().setData(Uint32Array.from(out.getPolys().getData()), 1); // Now, transform the cube polydata points in-place
829
- // using the image's indexToWorld transformation.
830
-
831
- var points = outPD.getPoints().getData();
832
- transformPoints(points, image.getIndexToWorld());
833
- }
834
-
835
793
  publicAPI.updateResliceGeometry = function () {
836
794
  var resGeomString = '';
837
795
  var image = model.currentInput;
@@ -900,8 +858,8 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
900
858
  model.resliceGeom.getPointData().setNormals(slicePD.getPointData().getNormals());
901
859
  } else if (slicePlane) {
902
860
  if (!orthoSlicing) {
903
- imageToCubePolyData(image, model.cubePolyData);
904
- model.cutter.setInputData(model.cubePolyData);
861
+ model.outlineFilter.setInputData(image);
862
+ model.cutter.setInputConnection(model.outlineFilter.getOutputPort());
905
863
  model.cutter.setCutFunction(slicePlane);
906
864
  model.lineToSurfaceFilter.setInputConnection(model.cutter.getOutputPort());
907
865
  model.lineToSurfaceFilter.update();
@@ -952,7 +910,8 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
952
910
  }
953
911
  }
954
912
 
955
- transformPoints(ptsArray, image.getIndexToWorld());
913
+ model.transform.setMatrix(image.getIndexToWorld());
914
+ model.transform.transformPoints(ptsArray, ptsArray);
956
915
  var cellArray = new Uint16Array(8);
957
916
  cellArray[0] = 3;
958
917
  cellArray[1] = 0;
@@ -1047,10 +1006,13 @@ function extend(publicAPI, model) {
1047
1006
  obj(model.VBOBuildTime);
1048
1007
  model.tmpMat4 = mat4.identity(new Float64Array(16)); // Implicit plane to polydata related cache:
1049
1008
 
1050
- model.cubeSource = vtkCubeSource.newInstance();
1009
+ model.outlineFilter = vtkImageDataOutlineFilter.newInstance();
1010
+ model.outlineFilter.setGenerateFaces(true);
1011
+ model.outlineFilter.setGenerateLines(false);
1051
1012
  model.cubePolyData = vtkPolyData.newInstance();
1052
1013
  model.cutter = vtkCutter.newInstance();
1053
1014
  model.lineToSurfaceFilter = vtkClosedPolyLineToSurfaceFilter.newInstance();
1015
+ model.transform = vtkTransform.newInstance();
1054
1016
  get(publicAPI, model, ['openGLTexture']); // Object methods
1055
1017
 
1056
1018
  vtkOpenGLImageResliceMapper(publicAPI, model);
@@ -365,6 +365,10 @@ function widgetBehavior(publicAPI, model) {
365
365
  var _manipulator$handleEv3 = manipulator.handleEvent(calldata, model._apiSpecificRenderWindow),
366
366
  worldCoords = _manipulator$handleEv3.worldCoords;
367
367
 
368
+ if (!worldCoords || !worldCoords.length) {
369
+ return;
370
+ }
371
+
368
372
  var center = model.widgetState.getCenter();
369
373
  var currentVectorToOrigin = [0, 0, 0];
370
374
  subtract(worldCoords, center, currentVectorToOrigin);
package/index.d.ts CHANGED
@@ -57,6 +57,7 @@
57
57
  /// <reference path="./Filters/General/ClipClosedSurface.d.ts" />
58
58
  /// <reference path="./Filters/General/ContourTriangulator.d.ts" />
59
59
  /// <reference path="./Filters/General/ImageCropFilter.d.ts" />
60
+ /// <reference path="./Filters/General/ImageDataOutlineFilter.d.ts" />
60
61
  /// <reference path="./Filters/General/ImageOutlineFilter.d.ts" />
61
62
  /// <reference path="./Filters/General/ImageSliceFilter.d.ts" />
62
63
  /// <reference path="./Filters/General/ImageStreamline.d.ts" />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitware/vtk.js",
3
- "version": "28.6.0",
3
+ "version": "28.8.0",
4
4
  "description": "Visualization Toolkit for the Web",
5
5
  "keywords": [
6
6
  "3d",