@kitware/vtk.js 34.15.0 → 34.15.2

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.
@@ -36,6 +36,10 @@ function vtkPolyData(publicAPI, model) {
36
36
  function camelize(str) {
37
37
  return str.replace(/(?:^\w|[A-Z]|\b\w)/g, letter => letter.toUpperCase()).replace(/\s+/g, '');
38
38
  }
39
+ function clearCells() {
40
+ model.cells = undefined;
41
+ model.links = undefined;
42
+ }
39
43
 
40
44
  // build empty cell arrays and set methods
41
45
  POLYDATA_FIELDS.forEach(type => {
@@ -45,6 +49,7 @@ function vtkPolyData(publicAPI, model) {
45
49
  } else {
46
50
  model[type] = vtk(model[type]);
47
51
  }
52
+ model[`_on${camelize(type)}Changed`] = clearCells;
48
53
  });
49
54
  publicAPI.getNumberOfCells = () => POLYDATA_FIELDS.reduce((num, cellType) => num + model[cellType].getNumberOfCells(), 0);
50
55
  const superShallowCopy = publicAPI.shallowCopy;
@@ -61,6 +66,7 @@ function vtkPolyData(publicAPI, model) {
61
66
  const superInitialize = publicAPI.initialize;
62
67
  publicAPI.initialize = () => {
63
68
  POLYDATA_FIELDS.forEach(type => model[type]?.initialize());
69
+ clearCells();
64
70
  return superInitialize();
65
71
  };
66
72
  publicAPI.buildCells = () => {
@@ -151,7 +157,7 @@ function vtkPolyData(publicAPI, model) {
151
157
  */
152
158
  publicAPI.buildLinks = function () {
153
159
  let initialSize = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
154
- if (model.cells === undefined) {
160
+ if (model.cells == null) {
155
161
  publicAPI.buildCells();
156
162
  }
157
163
  model.links = vtkCellLinks.newInstance();
@@ -47,19 +47,23 @@ function vtkViewport(publicAPI, model) {
47
47
  }
48
48
  publicAPI.getViewPropsWithNestedProps = () => {
49
49
  let allPropsArray = [];
50
- // Handle actor2D instances separately so that they can be overlayed and layered
51
- const actors2D = publicAPI.getActors2D();
52
- // Sort the actor2D list using its layer number
53
- actors2D.sort((a, b) => a.getLayerNumber() - b.getLayerNumber());
54
- // Filter out all the actor2D instances
55
- const newPropList = model.props.filter(item => !actors2D.includes(item));
56
- for (let i = 0; i < newPropList.length; i++) {
57
- gatherProps(newPropList[i], allPropsArray);
50
+ // Repopulate the actor2D list to minimize browsing operations.
51
+ model.actors2D = [];
52
+ for (let i = 0; i < model.props.length; i++) {
53
+ // Handle actor2D instances separately so that they can be overlayed and layered
54
+ const isActor2D = model.props[i].getActors2D();
55
+ if (isActor2D && (!Array.isArray(isActor2D) || isActor2D.length > 0)) {
56
+ model.actors2D = model.actors2D.concat(isActor2D);
57
+ } else {
58
+ gatherProps(model.props[i], allPropsArray);
59
+ }
58
60
  }
61
+ // Actor2D must be rendered by layer number order
62
+ model.actors2D.sort((a, b) => a.getLayerNumber() - b.getLayerNumber());
59
63
  // Finally, add the actor2D props at the end of the list
60
64
  // This works because, when traversing the render pass in vtkOpenGLRenderer, the children are
61
65
  // traversed in the order that they are added to the list
62
- allPropsArray = allPropsArray.concat(actors2D);
66
+ allPropsArray = allPropsArray.concat(model.actors2D);
63
67
  return allPropsArray;
64
68
  };
65
69
  publicAPI.addActor2D = publicAPI.addViewProp;
@@ -33,10 +33,14 @@ function convert(xx, yy, pb, area) {
33
33
  if (!pb) {
34
34
  return 0;
35
35
  }
36
+
37
+ // console.log(caller);
38
+ // console.log('convert', xx, yy, pb, area);
36
39
  const offset = (yy * (area[2] - area[0] + 1) + xx) * 4;
37
40
  const r = pb[offset];
38
41
  const g = pb[offset + 1];
39
42
  const b = pb[offset + 2];
43
+ // console.log(b, g, r, (b * 256 + g) * 256 + r);
40
44
  return (b * 256 + g) * 256 + r;
41
45
  }
42
46
  function getID(low24, high8) {
@@ -227,7 +231,7 @@ function vtkOpenGLHardwareSelector(publicAPI, model) {
227
231
 
228
232
  //----------------------------------------------------------------------------
229
233
  publicAPI.beginSelection = () => {
230
- model._openGLRenderer = model._openGLRenderWindow.getViewNodeFor(model._renderer);
234
+ model._openGLRenderer = model._openGLRenderWindow.getViewNodeFor(model._renderer, model._openGLRenderer);
231
235
  model.maxAttributeId = 0;
232
236
  const size = model._openGLRenderWindow.getSize();
233
237
  if (!model.framebuffer) {
@@ -335,7 +339,7 @@ function vtkOpenGLHardwareSelector(publicAPI, model) {
335
339
  vtkErrorMacro('Renderer and view must be set before calling Select.');
336
340
  return false;
337
341
  }
338
- model._openGLRenderer = model._openGLRenderWindow.getViewNodeFor(model._renderer);
342
+ model._openGLRenderer = model._openGLRenderWindow.getViewNodeFor(model._renderer, model._openGLRenderer);
339
343
 
340
344
  // todo revisit making selection part of core
341
345
  // then we can do this in core
@@ -507,16 +511,20 @@ function vtkOpenGLHardwareSelector(publicAPI, model) {
507
511
  publicAPI.getPixelInformation = (inDisplayPosition, maxDistance, outSelectedPosition) => {
508
512
  // Base case
509
513
  const maxDist = maxDistance < 0 ? 0 : maxDistance;
514
+ console.log('getPixelInformation called', maxDist);
510
515
  if (maxDist === 0) {
511
516
  outSelectedPosition[0] = inDisplayPosition[0];
512
517
  outSelectedPosition[1] = inDisplayPosition[1];
513
518
  if (inDisplayPosition[0] < model.area[0] || inDisplayPosition[0] > model.area[2] || inDisplayPosition[1] < model.area[1] || inDisplayPosition[1] > model.area[3]) {
514
519
  return null;
515
520
  }
516
-
521
+ console.log(inDisplayPosition);
522
+ console.log(model.area);
517
523
  // offset inDisplayPosition based on the lower-left-corner of the Area.
518
524
  const displayPosition = [inDisplayPosition[0] - model.area[0], inDisplayPosition[1] - model.area[1]];
525
+ console.log('adjusted displayPosition', displayPosition);
519
526
  const actorid = convert(displayPosition[0], displayPosition[1], model.pixBuffer[PassTypes.ACTOR_PASS], model.area);
527
+ console.log('actorid', actorid);
520
528
  if (actorid <= 0 || actorid - idOffset >= model.props.length) {
521
529
  // the pixel did not hit any actor.
522
530
  return null;
@@ -43,7 +43,7 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
43
43
  unregisterGraphicsResources(oldOglRenderWindow);
44
44
  }
45
45
  model.context = model._openGLRenderWindow.getContext();
46
- model.openGLCamera = model._openGLRenderer.getViewNodeFor(model._openGLRenderer.getRenderable().getActiveCamera());
46
+ model.openGLCamera = model._openGLRenderer.getViewNodeFor(model._openGLRenderer.getRenderable().getActiveCamera(), model.openGLCamera);
47
47
  model.tris.setOpenGLRenderWindow(model._openGLRenderWindow);
48
48
  }
49
49
  };
@@ -70,7 +70,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
70
70
  model.context = model._openGLRenderWindow.getContext();
71
71
  model.tris.setOpenGLRenderWindow(model._openGLRenderWindow);
72
72
  const ren = model._openGLRenderer.getRenderable();
73
- model.openGLCamera = model._openGLRenderer.getViewNodeFor(ren.getActiveCamera());
73
+ model.openGLCamera = model._openGLRenderer.getViewNodeFor(ren.getActiveCamera(), model.openGLCamera);
74
74
  // is slice set by the camera
75
75
  if (model.renderable.isA('vtkImageMapper') && model.renderable.getSliceAtFocalPoint()) {
76
76
  model.renderable.setSliceFromCamera(ren.getActiveCamera());
@@ -93,7 +93,7 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
93
93
  model._openGLImageSlice = publicAPI.getFirstAncestorOfType('vtkOpenGLImageSlice');
94
94
  model._openGLRenderer = publicAPI.getFirstAncestorOfType('vtkOpenGLRenderer');
95
95
  const ren = model._openGLRenderer.getRenderable();
96
- model._openGLCamera = model._openGLRenderer.getViewNodeFor(ren.getActiveCamera());
96
+ model._openGLCamera = model._openGLRenderer.getViewNodeFor(ren.getActiveCamera(), model.openGLCamera);
97
97
  const oldOglRenderWindow = model._openGLRenderWindow;
98
98
  model._openGLRenderWindow = model._openGLRenderer.getLastAncestorOfType('vtkOpenGLRenderWindow');
99
99
  if (oldOglRenderWindow && !oldOglRenderWindow.isDeleted() && oldOglRenderWindow !== model._openGLRenderWindow) {
@@ -70,7 +70,7 @@ function vtkOpenGLPolyDataMapper(publicAPI, model) {
70
70
  model.openGLActor = publicAPI.getFirstAncestorOfType('vtkOpenGLActor');
71
71
  model._openGLRenderer = model.openGLActor.getFirstAncestorOfType('vtkOpenGLRenderer');
72
72
  model._openGLRenderWindow = model._openGLRenderer.getLastAncestorOfType('vtkOpenGLRenderWindow');
73
- model.openGLCamera = model._openGLRenderer.getViewNodeFor(model._openGLRenderer.getRenderable().getActiveCamera());
73
+ model.openGLCamera = model._openGLRenderer.getViewNodeFor(model._openGLRenderer.getRenderable().getActiveCamera(), model.openGLCamera);
74
74
  }
75
75
  };
76
76
 
@@ -42,7 +42,7 @@ function vtkOpenGLPolyDataMapper2D(publicAPI, model) {
42
42
  model.openGLActor2D = publicAPI.getFirstAncestorOfType('vtkOpenGLActor2D');
43
43
  model._openGLRenderer = model.openGLActor2D.getFirstAncestorOfType('vtkOpenGLRenderer');
44
44
  model._openGLRenderWindow = model._openGLRenderer.getLastAncestorOfType('vtkOpenGLRenderWindow');
45
- model.openGLCamera = model._openGLRenderer.getViewNodeFor(model._openGLRenderer.getRenderable().getActiveCamera());
45
+ model.openGLCamera = model._openGLRenderer.getViewNodeFor(model._openGLRenderer.getRenderable().getActiveCamera(), model.openGLCamera);
46
46
  }
47
47
  };
48
48
  publicAPI.overlayPass = prepass => {
@@ -28,7 +28,7 @@ function vtkOpenGLSkybox(publicAPI, model) {
28
28
  model.tris.setOpenGLRenderWindow(model._openGLRenderWindow);
29
29
  model.openGLTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
30
30
  const ren = model._openGLRenderer.getRenderable();
31
- model.openGLCamera = model._openGLRenderer.getViewNodeFor(ren.getActiveCamera());
31
+ model.openGLCamera = model._openGLRenderer.getViewNodeFor(ren.getActiveCamera(), model.openGLCamera);
32
32
  }
33
33
  };
34
34
  publicAPI.queryPass = (prepass, renderPass) => {
@@ -124,7 +124,7 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
124
124
  const actor = model.openGLVolume.getRenderable();
125
125
  model._openGLRenderer = publicAPI.getFirstAncestorOfType('vtkOpenGLRenderer');
126
126
  const ren = model._openGLRenderer.getRenderable();
127
- model.openGLCamera = model._openGLRenderer.getViewNodeFor(ren.getActiveCamera());
127
+ model.openGLCamera = model._openGLRenderer.getViewNodeFor(ren.getActiveCamera(), model.openGLCamera);
128
128
  publicAPI.renderPiece(ren, actor);
129
129
  }
130
130
  };
@@ -100,8 +100,9 @@ export interface vtkViewNode extends vtkObject {
100
100
  * Returns the view node that corresponding to the provided object
101
101
  * Will return NULL if a match is not found in self or descendents
102
102
  * @param dataObject
103
+ * @param [hint] the previously found node (for optimization)
103
104
  */
104
- getViewNodeFor(dataObject: any): any;
105
+ getViewNodeFor(dataObject: any, hint?: any): any;
105
106
 
106
107
  /**
107
108
  *
@@ -13,6 +13,25 @@ function vtkViewNode(publicAPI, model) {
13
13
  // Set our className
14
14
  model.classHierarchy.push('vtkViewNode');
15
15
 
16
+ /**
17
+ * Convenient method to move a child to a specific index.
18
+ * @param {*} child the child to move
19
+ * @param {*} toIndex the index to move the child to
20
+ * @returns true if the child was moved, false otherwise
21
+ */
22
+ function moveChild(child, toIndex) {
23
+ for (let i = 0; i < model.children.length; ++i) {
24
+ // Start browsing from toIndex + 1
25
+ const childIndex = (toIndex + 1 + i) % model.children.length;
26
+ if (model.children[childIndex] === child) {
27
+ model.children[childIndex] = model.children[toIndex];
28
+ model.children[toIndex] = child;
29
+ return true;
30
+ }
31
+ }
32
+ return false;
33
+ }
34
+
16
35
  // Builds myself.
17
36
  publicAPI.build = prepass => {};
18
37
 
@@ -41,7 +60,11 @@ function vtkViewNode(publicAPI, model) {
41
60
  customRenderPass(prepass, renderPass);
42
61
  }
43
62
  };
44
- publicAPI.getViewNodeFor = dataObject => {
63
+ publicAPI.getViewNodeFor = function (dataObject) {
64
+ let hint = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
65
+ if (hint && hint.renderable === dataObject) {
66
+ return hint;
67
+ }
45
68
  if (model.renderable === dataObject) {
46
69
  return publicAPI;
47
70
  }
@@ -110,17 +133,19 @@ function vtkViewNode(publicAPI, model) {
110
133
  if (!dataObjs || !dataObjs.length) {
111
134
  return;
112
135
  }
136
+ let nextIndex;
113
137
  for (let index = 0; index < dataObjs.length; ++index) {
114
138
  const dobj = dataObjs[index];
115
139
  const node = publicAPI.addMissingNode(dobj);
116
- if (enforceOrder && node !== undefined && model.children[index] !== node) {
117
- for (let i = index + 1; i < model.children.length; ++i) {
118
- if (model.children[i] === node) {
119
- model.children.splice(i, 1);
120
- model.children.splice(index, 0, node);
121
- break;
122
- }
140
+ if (enforceOrder && node !== undefined) {
141
+ if (nextIndex === undefined) {
142
+ // First node can be anywhere
143
+ nextIndex = model.children.lastIndexOf(node); // node is likely the list child
144
+ } else if (model.children[nextIndex] !== node) {
145
+ moveChild(model.children, node);
123
146
  }
147
+ // Next node must follow current node
148
+ nextIndex++;
124
149
  }
125
150
  }
126
151
  };
@@ -122,7 +122,7 @@ function vtkWebGPURenderer(publicAPI, model) {
122
122
  publicAPI.addMissingNode(model.camera);
123
123
  publicAPI.addMissingNodes(model.renderable.getViewPropsWithNestedProps());
124
124
  publicAPI.removeUnusedNodes();
125
- model.webgpuCamera = publicAPI.getViewNodeFor(model.camera);
125
+ model.webgpuCamera = publicAPI.getViewNodeFor(model.camera, model.webgpuCamera);
126
126
  publicAPI.updateStabilizedMatrix();
127
127
  }
128
128
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitware/vtk.js",
3
- "version": "34.15.0",
3
+ "version": "34.15.2",
4
4
  "description": "Visualization Toolkit for the Web",
5
5
  "keywords": [
6
6
  "3d",
@@ -97,6 +97,7 @@
97
97
  "karma-junit-reporter": "2.0.1",
98
98
  "karma-webpack": "5.0.0",
99
99
  "kw-doc": "3.1.2",
100
+ "lil-gui": "0.19.2",
100
101
  "lodash": "4.17.21",
101
102
  "magic-string": "0.26.2",
102
103
  "moment": "2.29.4",