@kitware/vtk.js 33.0.1 → 33.1.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.
@@ -13,7 +13,19 @@ interface IPLYReaderOptions {
13
13
  /**
14
14
  *
15
15
  */
16
- export interface IPLYReaderInitialValues {}
16
+ export interface IPLYReaderInitialValues {
17
+ /**
18
+ * Controls whether points are duplicated for face-texture mapping.
19
+ * Default is true.
20
+ */
21
+ duplicatePointsForFaceTexture?: boolean;
22
+
23
+ /**
24
+ * The tolerance used to determine if two points are the same.
25
+ * Default is 0.000001.
26
+ */
27
+ faceTextureTolerance?: number;
28
+ }
17
29
 
18
30
  type vtkPLYReaderBase = vtkObject &
19
31
  Omit<
@@ -41,6 +53,16 @@ export interface vtkPLYReader extends vtkPLYReaderBase {
41
53
  | JSZipDataAccessHelper
42
54
  | LiteHttpDataAccessHelper;
43
55
 
56
+ /**
57
+ * Controls whether points are duplicated for face-texture mapping.
58
+ */
59
+ getDuplicatePointsForFaceTexture(): boolean;
60
+
61
+ /**
62
+ * Get the tolerance used to determine if two points are the same.
63
+ */
64
+ getFaceTextureTolerance(): number;
65
+
44
66
  /**
45
67
  * Get the url of the object to load.
46
68
  */
@@ -95,7 +95,7 @@ function parseHeader(data) {
95
95
  }
96
96
  return header;
97
97
  }
98
- function postProcess(buffer, elements) {
98
+ function postProcess(buffer, elements, faceTextureTolerance, duplicatePointsForFaceTexture) {
99
99
  const vertElement = elements.find(element => element.name === 'vertex');
100
100
  const faceElement = elements.find(element => element.name === 'face');
101
101
  let nbVerts = 0;
@@ -106,14 +106,20 @@ function postProcess(buffer, elements) {
106
106
  if (faceElement) {
107
107
  nbFaces = faceElement.count;
108
108
  }
109
- const pointValues = new Float32Array(nbVerts * 3);
110
- const colorArray = new Uint8Array(nbVerts * 3);
111
- const tcoordsArray = new Float32Array(nbVerts * 2);
112
- const normalsArray = new Float32Array(nbVerts * 3);
109
+ let pointValues = new Float32Array(nbVerts * 3);
110
+ let colorArray = new Uint8Array(nbVerts * 3);
111
+ let tcoordsArray = new Float32Array(nbVerts * 2);
112
+ let normalsArray = new Float32Array(nbVerts * 3);
113
113
  const hasColor = buffer.colors.length > 0;
114
114
  const hasVertTCoords = buffer.uvs.length > 0;
115
115
  const hasNorms = buffer.normals.length > 0;
116
116
  const hasFaceTCoords = buffer.faceVertexUvs.length > 0;
117
+
118
+ // For duplicate point handling
119
+ const pointIds = new Map(); // Maps texture coords to arrays of point IDs
120
+ let nextPointId = nbVerts;
121
+
122
+ // Initialize base points
117
123
  for (let vertIdx = 0; vertIdx < nbVerts; vertIdx++) {
118
124
  let a = vertIdx * 3 + 0;
119
125
  let b = vertIdx * 3 + 1;
@@ -131,6 +137,10 @@ function postProcess(buffer, elements) {
131
137
  b = vertIdx * 2 + 1;
132
138
  tcoordsArray[a] = buffer.uvs[a];
133
139
  tcoordsArray[b] = buffer.uvs[b];
140
+ } else {
141
+ // Initialize with sentinel value
142
+ tcoordsArray[vertIdx * 2] = -1;
143
+ tcoordsArray[vertIdx * 2 + 1] = -1;
134
144
  }
135
145
  if (hasNorms) {
136
146
  normalsArray[a] = buffer.normals[a];
@@ -138,33 +148,153 @@ function postProcess(buffer, elements) {
138
148
  normalsArray[c] = buffer.normals[c];
139
149
  }
140
150
  }
141
- if (!hasVertTCoords && hasFaceTCoords) {
151
+
152
+ // Process face texture coordinates
153
+ if (hasFaceTCoords && !hasVertTCoords && nbFaces > 0) {
142
154
  // don't use array.shift, because buffer.indices will be used later
143
155
  let idxVerts = 0;
144
156
  let idxCoord = 0;
145
- for (let faceIdx = 0; faceIdx < nbFaces; ++faceIdx) {
146
- const nbFaceVerts = buffer.indices[idxVerts++];
147
- const texcoords = buffer.faceVertexUvs[idxCoord++];
148
- if (texcoords && nbFaceVerts * 2 === texcoords.length) {
149
- // grab the vertex index
150
- for (let vertIdx = 0; vertIdx < nbFaceVerts; ++vertIdx) {
151
- const vert = buffer.indices[idxVerts++];
152
- // new texture stored at the current face
153
- tcoordsArray[vert * 2 + 0] = texcoords[vertIdx * 2 + 0];
154
- tcoordsArray[vert * 2 + 1] = texcoords[vertIdx * 2 + 1];
157
+ if (duplicatePointsForFaceTexture) {
158
+ // Arrays to store duplicated point data
159
+ const extraPoints = [];
160
+ const extraColors = [];
161
+ const extraNormals = [];
162
+ const extraTCoords = [];
163
+ for (let faceIdx = 0; faceIdx < nbFaces; ++faceIdx) {
164
+ const nbFaceVerts = buffer.indices[idxVerts++];
165
+ const texcoords = buffer.faceVertexUvs[idxCoord++];
166
+ if (texcoords && nbFaceVerts * 2 === texcoords.length) {
167
+ for (let vertIdx = 0; vertIdx < nbFaceVerts; ++vertIdx) {
168
+ const vertId = buffer.indices[idxVerts + vertIdx];
169
+ const newTex = [texcoords[vertIdx * 2], texcoords[vertIdx * 2 + 1]];
170
+ const currentTex = [tcoordsArray[vertId * 2], tcoordsArray[vertId * 2 + 1]];
171
+ if (currentTex[0] === -1) {
172
+ // First time seeing texture coordinates for this vertex
173
+ tcoordsArray[vertId * 2] = newTex[0];
174
+ tcoordsArray[vertId * 2 + 1] = newTex[1];
175
+ const key = `${newTex[0]},${newTex[1]}`;
176
+ if (!pointIds.has(key)) {
177
+ pointIds.set(key, []);
178
+ }
179
+ pointIds.get(key).push(vertId);
180
+ } else {
181
+ // Check if we need to duplicate the vertex
182
+ const needsDuplication = Math.abs(currentTex[0] - newTex[0]) > faceTextureTolerance || Math.abs(currentTex[1] - newTex[1]) > faceTextureTolerance;
183
+ if (needsDuplication) {
184
+ const key = `${newTex[0]},${newTex[1]}`;
185
+ let existingPointId = -1;
186
+
187
+ // Check if we already have a point with these texture coordinates
188
+ if (pointIds.has(key)) {
189
+ const candidates = pointIds.get(key);
190
+ for (let i = 0, len = candidates.length; i < len; i++) {
191
+ const candidateId = candidates[i];
192
+ const samePosition = Math.abs(pointValues[candidateId * 3] - pointValues[vertId * 3]) <= faceTextureTolerance && Math.abs(pointValues[candidateId * 3 + 1] - pointValues[vertId * 3 + 1]) <= faceTextureTolerance && Math.abs(pointValues[candidateId * 3 + 2] - pointValues[vertId * 3 + 2]) <= faceTextureTolerance;
193
+ if (samePosition) {
194
+ existingPointId = candidateId;
195
+ break;
196
+ }
197
+ }
198
+ }
199
+ if (existingPointId === -1) {
200
+ // Create new point
201
+ extraPoints.push(pointValues[vertId * 3], pointValues[vertId * 3 + 1], pointValues[vertId * 3 + 2]);
202
+ if (hasColor) {
203
+ extraColors.push(colorArray[vertId * 3], colorArray[vertId * 3 + 1], colorArray[vertId * 3 + 2]);
204
+ }
205
+ if (hasNorms) {
206
+ extraNormals.push(normalsArray[vertId * 3], normalsArray[vertId * 3 + 1], normalsArray[vertId * 3 + 2]);
207
+ }
208
+ extraTCoords.push(newTex[0], newTex[1]);
209
+ if (!pointIds.has(key)) {
210
+ pointIds.set(key, []);
211
+ }
212
+ pointIds.get(key).push(nextPointId);
213
+ buffer.indices[idxVerts + vertIdx] = nextPointId;
214
+ nextPointId++;
215
+ } else {
216
+ buffer.indices[idxVerts + vertIdx] = existingPointId;
217
+ }
218
+ }
219
+ }
220
+ }
155
221
  }
156
- } else {
157
222
  idxVerts += nbFaceVerts;
158
223
  }
224
+
225
+ // Extend arrays with duplicated points if needed
226
+ if (extraPoints.length > 0) {
227
+ const newPointCount = nbVerts + extraPoints.length / 3;
228
+ const newPointValues = new Float32Array(newPointCount * 3);
229
+ const newTcoordsArray = new Float32Array(newPointCount * 2);
230
+ const newColorArray = hasColor ? new Uint8Array(newPointCount * 3) : null;
231
+ const newNormalsArray = hasNorms ? new Float32Array(newPointCount * 3) : null;
232
+
233
+ // Copy existing data
234
+ newPointValues.set(pointValues);
235
+ newTcoordsArray.set(tcoordsArray);
236
+ if (hasColor && newColorArray) {
237
+ newColorArray.set(colorArray);
238
+ }
239
+ if (hasNorms && newNormalsArray) {
240
+ newNormalsArray.set(normalsArray);
241
+ }
242
+
243
+ // Add new data
244
+ newPointValues.set(extraPoints, nbVerts * 3);
245
+ newTcoordsArray.set(extraTCoords, nbVerts * 2);
246
+ if (hasColor && newColorArray) {
247
+ newColorArray.set(extraColors, nbVerts * 3);
248
+ }
249
+ if (hasNorms && newNormalsArray) {
250
+ newNormalsArray.set(extraNormals, nbVerts * 3);
251
+ }
252
+ pointValues = newPointValues;
253
+ tcoordsArray = newTcoordsArray;
254
+ if (hasColor) {
255
+ colorArray = newColorArray;
256
+ }
257
+ if (hasNorms) {
258
+ normalsArray = newNormalsArray;
259
+ }
260
+ }
261
+ } else {
262
+ for (let faceIdx = 0; faceIdx < nbFaces; ++faceIdx) {
263
+ const nbFaceVerts = buffer.indices[idxVerts++];
264
+ const texcoords = buffer.faceVertexUvs[idxCoord++];
265
+ if (texcoords && nbFaceVerts * 2 === texcoords.length) {
266
+ for (let vertIdx = 0; vertIdx < nbFaceVerts; ++vertIdx) {
267
+ const vert = buffer.indices[idxVerts++];
268
+ tcoordsArray[vert * 2] = texcoords[vertIdx * 2];
269
+ tcoordsArray[vert * 2 + 1] = texcoords[vertIdx * 2 + 1];
270
+ }
271
+ } else {
272
+ idxVerts += nbFaceVerts;
273
+ }
274
+ }
159
275
  }
160
276
  }
161
277
  const polydata = vtkPolyData.newInstance();
162
278
  polydata.getPoints().setData(pointValues, 3);
279
+
280
+ // If we have faces, add them as polys
281
+ if (nbFaces > 0) {
282
+ polydata.getPolys().setData(Uint32Array.from(buffer.indices));
283
+ } else {
284
+ // Point cloud - create a vertex list containing all points
285
+ const verts = new Uint32Array(nbVerts * 2);
286
+ for (let i = 0; i < nbVerts; i++) {
287
+ verts[i * 2] = 1; // number of points in vertex cell (always 1)
288
+ verts[i * 2 + 1] = i; // point index
289
+ }
290
+
291
+ polydata.getVerts().setData(verts);
292
+ }
163
293
  if (hasColor) {
164
294
  polydata.getPointData().setScalars(vtkDataArray.newInstance({
165
295
  numberOfComponents: 3,
166
296
  values: colorArray,
167
- name: 'Scalars'
297
+ name: 'RGB'
168
298
  }));
169
299
  }
170
300
  if (hasVertTCoords || hasFaceTCoords) {
@@ -184,7 +314,6 @@ function postProcess(buffer, elements) {
184
314
  values: normalsArray
185
315
  }));
186
316
  }
187
- polydata.getPolys().setData(Uint32Array.from(buffer.indices));
188
317
  return polydata;
189
318
  }
190
319
  function parseNumber(n, type) {
@@ -410,7 +539,10 @@ function vtkPLYReader(publicAPI, model) {
410
539
  }
411
540
 
412
541
  // Header
413
- const text = BinaryHelper.arrayBufferToString(content);
542
+ let text = content;
543
+ if (content instanceof ArrayBuffer) {
544
+ text = BinaryHelper.arrayBufferToString(content);
545
+ }
414
546
  const header = parseHeader(text);
415
547
 
416
548
  // ascii/binary detection
@@ -418,7 +550,7 @@ function vtkPLYReader(publicAPI, model) {
418
550
 
419
551
  // Check if ascii format
420
552
  if (!isBinary) {
421
- publicAPI.parseAsText(content);
553
+ publicAPI.parseAsText(text);
422
554
  return;
423
555
  }
424
556
  model.parseData = content;
@@ -445,7 +577,7 @@ function vtkPLYReader(publicAPI, model) {
445
577
  handleElement(buffer, header.elements[elem].name, element);
446
578
  }
447
579
  }
448
- const polydata = postProcess(buffer, header.elements);
580
+ const polydata = postProcess(buffer, header.elements, model.faceTextureTolerance, model.duplicatePointsForFaceTexture);
449
581
 
450
582
  // Add new output
451
583
  model.output[0] = polydata;
@@ -462,7 +594,10 @@ function vtkPLYReader(publicAPI, model) {
462
594
  model.parseData = content;
463
595
 
464
596
  // Header
465
- const text = BinaryHelper.arrayBufferToString(content);
597
+ let text = content;
598
+ if (content instanceof ArrayBuffer) {
599
+ text = BinaryHelper.arrayBufferToString(content);
600
+ }
466
601
  const header = parseHeader(text);
467
602
 
468
603
  // ascii/binary detection
@@ -504,7 +639,7 @@ function vtkPLYReader(publicAPI, model) {
504
639
  idx++;
505
640
  }
506
641
  }
507
- const polydata = postProcess(buffer, header.elements);
642
+ const polydata = postProcess(buffer, header.elements, model.faceTextureTolerance, model.duplicatePointsForFaceTexture);
508
643
 
509
644
  // Add new output
510
645
  model.output[0] = polydata;
@@ -522,6 +657,8 @@ const DEFAULT_VALUES = {
522
657
  // baseURL: null,
523
658
  // dataAccessHelper: null,
524
659
  // url: null,
660
+ faceTextureTolerance: 1e-6,
661
+ duplicatePointsForFaceTexture: true
525
662
  };
526
663
 
527
664
  // ----------------------------------------------------------------------------
@@ -532,7 +669,7 @@ function extend(publicAPI, model) {
532
669
 
533
670
  // Build VTK API
534
671
  macro.obj(publicAPI, model);
535
- macro.get(publicAPI, model, ['url', 'baseURL']);
672
+ macro.get(publicAPI, model, ['url', 'baseURL', 'duplicatePointsForFaceTexture', 'faceTextureTolerance']);
536
673
  macro.setGet(publicAPI, model, ['dataAccessHelper']);
537
674
  macro.algo(publicAPI, model, 0, 1);
538
675
 
@@ -13,77 +13,35 @@ function vtkMouseCameraTrackballFirstPersonManipulator(publicAPI, model) {
13
13
  model.classHierarchy.push('vtkMouseCameraTrackballFirstPersonManipulator');
14
14
  const internal = {
15
15
  interactor: null,
16
- renderer: null,
17
- previousPosition: null
16
+ renderer: null
18
17
  };
19
18
 
20
19
  //--------------------------------------------------------------------------
21
20
 
22
21
  publicAPI.onButtonDown = (interactor, renderer, position) => {
23
- internal.previousPosition = position;
24
22
  if (model.usePointerLock && !interactor.isPointerLocked()) {
25
23
  Object.assign(internal, {
26
24
  interactor,
27
25
  renderer
28
26
  });
29
27
  interactor.requestPointerLock();
30
- publicAPI.startPointerLockInteraction();
31
28
  }
32
29
  };
33
30
 
34
31
  //--------------------------------------------------------------------------
35
32
 
36
- publicAPI.startPointerLockInteraction = () => {
37
- const {
38
- interactor
39
- } = internal;
40
-
41
- // TODO: at some point, this should perhaps be done in
42
- // RenderWindowInteractor instead of here.
43
- // We need to hook into mousemove directly for two reasons:
44
- // 1. We need to keep receiving mouse move events after the mouse button
45
- // is released. This is currently not possible with
46
- // vtkInteractorStyleManipulator.
47
- // 2. Since the mouse is stationary in pointer lock mode, we need the
48
- // event.movementX and event.movementY info, which are not currently
49
- // passed via interactor.onMouseMove.
50
- document.addEventListener('mousemove', publicAPI.onPointerLockMove);
51
- let subscription = null;
52
- const endInteraction = () => {
53
- document.removeEventListener('mousemove', publicAPI.onPointerLockMove);
54
- subscription.unsubscribe();
55
- };
56
- subscription = interactor.onEndPointerLock(endInteraction);
57
- };
58
-
59
- //--------------------------------------------------------------------------
60
-
61
- publicAPI.onPointerLockMove = e => {
62
- const sensitivity = model.sensitivity;
63
- const yaw = -1 * e.movementX * sensitivity;
64
- const pitch = -1 * e.movementY * sensitivity;
65
- publicAPI.moveCamera(yaw, pitch);
66
- };
67
-
68
- //--------------------------------------------------------------------------
69
-
70
33
  publicAPI.onMouseMove = (interactor, renderer, position) => {
71
- // This is currently only being called for non pointer lock mode
72
34
  if (!position) {
73
35
  return;
74
36
  }
75
- const {
76
- previousPosition
77
- } = internal;
78
37
  const sensitivity = model.sensitivity;
79
- const yaw = (previousPosition.x - position.x) * sensitivity;
80
- const pitch = (position.y - previousPosition.y) * sensitivity;
38
+ const yaw = -position.movementX * sensitivity;
39
+ const pitch = -position.movementY * sensitivity;
81
40
  Object.assign(internal, {
82
41
  interactor,
83
42
  renderer
84
43
  });
85
44
  publicAPI.moveCamera(yaw, pitch);
86
- internal.previousPosition = position;
87
45
  };
88
46
 
89
47
  //--------------------------------------------------------------------------
@@ -6,6 +6,7 @@ import vtkInteractorStyle from './../../Rendering/Core/InteractorStyle';
6
6
  import {
7
7
  Device,
8
8
  Input,
9
+ MouseButton,
9
10
  } from './../../Rendering/Core/RenderWindowInteractor/Constants';
10
11
  import { Nullable, Vector3 } from './../../types';
11
12
 
@@ -120,7 +121,7 @@ export interface vtkInteractorStyleManipulator extends vtkInteractorStyle {
120
121
  * @param alt alt enabled
121
122
  */
122
123
  findMouseManipulator(
123
- button: number,
124
+ button: MouseButton,
124
125
  shift: boolean,
125
126
  scroll: boolean,
126
127
  alt: boolean
@@ -285,13 +286,13 @@ export interface vtkInteractorStyleManipulator extends vtkInteractorStyle {
285
286
  * @param button which button
286
287
  * @param callData event data
287
288
  */
288
- onButtonDown(button: number, callData: unknown): void;
289
+ onButtonDown(button: MouseButton, callData: unknown): void;
289
290
 
290
291
  /**
291
292
  * Handles a button up event.
292
293
  * @param button which button
293
294
  */
294
- onButtonUp(button: number): void;
295
+ onButtonUp(button: MouseButton): void;
295
296
 
296
297
  /**
297
298
  * Sets the rotation factor.
@@ -1,4 +1,5 @@
1
1
  import { m as macro } from '../../macros2.js';
2
+ import { MouseButton } from '../../Rendering/Core/RenderWindowInteractor/Constants.js';
2
3
  import vtkInteractorStyle from '../../Rendering/Core/InteractorStyle.js';
3
4
 
4
5
  const {
@@ -225,19 +226,19 @@ function vtkInteractorStyleManipulator(publicAPI, model) {
225
226
  //-------------------------------------------------------------------------
226
227
  publicAPI.handleLeftButtonPress = callData => {
227
228
  model.previousPosition = callData.position;
228
- publicAPI.onButtonDown(1, callData);
229
+ publicAPI.onButtonDown(MouseButton.LeftButton, callData);
229
230
  };
230
231
 
231
232
  //-------------------------------------------------------------------------
232
233
  publicAPI.handleMiddleButtonPress = callData => {
233
234
  model.previousPosition = callData.position;
234
- publicAPI.onButtonDown(2, callData);
235
+ publicAPI.onButtonDown(MouseButton.MiddleButton, callData);
235
236
  };
236
237
 
237
238
  //-------------------------------------------------------------------------
238
239
  publicAPI.handleRightButtonPress = callData => {
239
240
  model.previousPosition = callData.position;
240
- publicAPI.onButtonDown(3, callData);
241
+ publicAPI.onButtonDown(MouseButton.RightButton, callData);
241
242
  };
242
243
 
243
244
  //-------------------------------------------------------------------------
@@ -330,17 +331,17 @@ function vtkInteractorStyleManipulator(publicAPI, model) {
330
331
 
331
332
  //-------------------------------------------------------------------------
332
333
  publicAPI.handleLeftButtonRelease = () => {
333
- publicAPI.onButtonUp(1);
334
+ publicAPI.onButtonUp(MouseButton.LeftButton);
334
335
  };
335
336
 
336
337
  //-------------------------------------------------------------------------
337
338
  publicAPI.handleMiddleButtonRelease = () => {
338
- publicAPI.onButtonUp(2);
339
+ publicAPI.onButtonUp(MouseButton.MiddleButton);
339
340
  };
340
341
 
341
342
  //-------------------------------------------------------------------------
342
343
  publicAPI.handleRightButtonRelease = () => {
343
- publicAPI.onButtonUp(3);
344
+ publicAPI.onButtonUp(MouseButton.RightButton);
344
345
  };
345
346
 
346
347
  //-------------------------------------------------------------------------
@@ -351,12 +352,18 @@ function vtkInteractorStyleManipulator(publicAPI, model) {
351
352
  if (model.currentManipulator.getButton && model.currentManipulator.getButton() === button) {
352
353
  model.currentManipulator.onButtonUp(model._interactor);
353
354
  model.currentManipulator.endInteraction();
354
- model.currentManipulator = null;
355
- model._interactor.cancelAnimation(publicAPI.onButtonDown);
355
+ if (!model._interactor.isPointerLocked()) {
356
+ model.currentManipulator = null;
357
+ }
356
358
  publicAPI.invokeEndInteractionEvent(END_INTERACTION_EVENT);
357
359
  }
358
360
  };
359
361
 
362
+ //-------------------------------------------------------------------------
363
+ publicAPI.handleEndPointerLock = () => {
364
+ model.currentManipulator = null;
365
+ };
366
+
360
367
  //-------------------------------------------------------------------------
361
368
  publicAPI.handleStartMouseWheel = callData => {
362
369
  // Must not be processing a wheel interaction to start another.
@@ -312,6 +312,30 @@ export interface vtkColorTransferFunction extends vtkScalarsToColors {
312
312
  * @param colorMap
313
313
  */
314
314
  applyColorMap(colorMap: any): void;
315
+
316
+ /**
317
+ * Get the color space of the color transfer function.
318
+ * @returns {ColorSpace}
319
+ */
320
+ getColorSpace(): ColorSpace;
321
+
322
+ /**
323
+ * Set the color space of the color transfer function.
324
+ * @param {ColorSpace} colorSpace
325
+ */
326
+ setColorSpace(colorSpace: ColorSpace): void;
327
+
328
+ /**
329
+ * Get the scale of the color transfer function.
330
+ * @returns {Scale}
331
+ */
332
+ getScale(): Scale;
333
+
334
+ /**
335
+ * Set the scale of the color transfer function.
336
+ * @param {Scale} scale
337
+ */
338
+ setScale(scale: Scale): void;
315
339
  }
316
340
 
317
341
  /**
@@ -135,12 +135,13 @@ const colorTextureCoordinatesCache = new WeakMap();
135
135
  * @param {vtkDataArray} input The input data array used for coloring
136
136
  * @param {Number} component The component of the input data array that is used for coloring (-1 for magnitude of the vectors)
137
137
  * @param {Range} range The range of the scalars
138
+ * @param {boolean} useLogScale Should the values be transformed to logarithmic scale. When true, the range must already be in logarithmic scale.
138
139
  * @param {Number} numberOfColorsInRange The number of colors that are used in the range
139
140
  * @param {vec3} dimensions The dimensions of the texture
140
141
  * @param {boolean} useZigzagPattern If a zigzag pattern should be used. Otherwise 1 row for colors (including min and max) and 1 row for NaN are used.
141
142
  * @returns A vtkDataArray containing the texture coordinates (2D or 3D)
142
143
  */
143
- function getOrCreateColorTextureCoordinates(input, component, range, numberOfColorsInRange, dimensions, useZigzagPattern) {
144
+ function getOrCreateColorTextureCoordinates(input, component, range, useLogScale, numberOfColorsInRange, dimensions, useZigzagPattern) {
144
145
  // Caching using the "arguments" special object (because it is a pure function)
145
146
  const argStrings = new Array(arguments.length);
146
147
  for (let argIndex = 0; argIndex < arguments.length; ++argIndex) {
@@ -199,6 +200,9 @@ function getOrCreateColorTextureCoordinates(input, component, range, numberOfCol
199
200
  } else {
200
201
  scalarValue = inputV[inputIdx + component];
201
202
  }
203
+ if (useLogScale) {
204
+ scalarValue = Math.log10(scalarValue);
205
+ }
202
206
  inputIdx += numComps;
203
207
 
204
208
  // Convert to texture coordinates and update output
@@ -396,6 +400,7 @@ function vtkMapper(publicAPI, model) {
396
400
  const range = model.lookupTable.getRange();
397
401
  const useLogScale = model.lookupTable.usingLogScale();
398
402
  const origAlpha = model.lookupTable.getAlpha();
403
+ const scaledRange = useLogScale ? [Math.log10(range[0]), Math.log10(range[1])] : range;
399
404
 
400
405
  // Get rid of vertex color array. Only texture or vertex coloring
401
406
  // can be active at one time. The existence of the array is the
@@ -438,7 +443,6 @@ function vtkMapper(publicAPI, model) {
438
443
  const numberOfNonSpecialColors = model.numberOfColorsInRange;
439
444
  const numberOfNonNaNColors = numberOfNonSpecialColors + 2;
440
445
  const textureCoordinates = [0, 0, 0];
441
- const scaledRange = useLogScale ? [Math.log10(range[0]), Math.log10(range[1])] : range;
442
446
  const rangeMin = scaledRange[0];
443
447
  const rangeDifference = scaledRange[1] - scaledRange[0];
444
448
  for (let i = 0; i < numberOfNonNaNColors; ++i) {
@@ -472,7 +476,7 @@ function vtkMapper(publicAPI, model) {
472
476
  // A zigzag pattern can be used with cell data, as there will be no texture coordinates interpolation
473
477
  // The texture generated using a zigzag pattern in one dimension is the same as without zigzag
474
478
  // Therefore, the same code can be used for texture generation of point/cell data but not for texture coordinates
475
- model.colorCoordinates = getOrCreateColorTextureCoordinates(scalars, scalarComponent, range, model.numberOfColorsInRange, model.colorTextureMap.getDimensions(), cellFlag);
479
+ model.colorCoordinates = getOrCreateColorTextureCoordinates(scalars, scalarComponent, scaledRange, useLogScale, model.numberOfColorsInRange, model.colorTextureMap.getDimensions(), cellFlag);
476
480
  };
477
481
  publicAPI.getIsOpaque = () => {
478
482
  const input = publicAPI.getInputData();
@@ -23,9 +23,16 @@ export declare enum Axis {
23
23
  ThumbstickY = 4,
24
24
  }
25
25
 
26
+ export declare enum MouseButton {
27
+ LeftButton = 1,
28
+ MiddleButton = 2,
29
+ RightButton = 3,
30
+ }
31
+
26
32
  declare const _default: {
27
33
  Device: typeof Device;
28
34
  Input: typeof Input;
29
35
  Axis: typeof Axis;
36
+ MouseButton: typeof MouseButton;
30
37
  };
31
38
  export default _default;
@@ -21,10 +21,16 @@ const Axis = {
21
21
  ThumbstickX: 3,
22
22
  ThumbstickY: 4
23
23
  };
24
+ const MouseButton = {
25
+ LeftButton: 1,
26
+ MiddleButton: 2,
27
+ RightButton: 3
28
+ };
24
29
  var Constants = {
25
30
  Device,
26
31
  Input,
27
- Axis
32
+ Axis,
33
+ MouseButton
28
34
  };
29
35
 
30
- export { Axis, Device, Input, Constants as default };
36
+ export { Axis, Device, Input, MouseButton, Constants as default };
@@ -1,7 +1,7 @@
1
1
  import { vtkObject, vtkSubscription } from './../../interfaces';
2
2
  import { Nullable } from './../../types';
3
3
  import vtkRenderer from './Renderer';
4
- import { Axis, Device, Input } from './RenderWindowInteractor/Constants';
4
+ import { Axis, Device, Input, MouseButton } from './RenderWindowInteractor/Constants';
5
5
 
6
6
  declare enum handledEvents {
7
7
  'StartAnimation',
@@ -1397,5 +1397,6 @@ export declare const vtkRenderWindowInteractor: {
1397
1397
  Device: typeof Device;
1398
1398
  Input: typeof Input;
1399
1399
  Axis: typeof Axis;
1400
+ MouseButton: typeof MouseButton;
1400
1401
  };
1401
1402
  export default vtkRenderWindowInteractor;
@@ -136,7 +136,9 @@ function vtkRenderWindowInteractor(publicAPI, model) {
136
136
  const position = {
137
137
  x: scaleX * (source.clientX - bounds.left),
138
138
  y: scaleY * (bounds.height - source.clientY + bounds.top),
139
- z: 0
139
+ z: 0,
140
+ movementX: scaleX * source.movementX,
141
+ movementY: scaleY * source.movementY
140
142
  };
141
143
 
142
144
  // if multitouch, do not update the current renderer
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitware/vtk.js",
3
- "version": "33.0.1",
3
+ "version": "33.1.0",
4
4
  "description": "Visualization Toolkit for the Web",
5
5
  "keywords": [
6
6
  "3d",