Skip to content

Commit 47d4061

Browse files
committed
perf(Math): Create and use arrayMin and arrayMax
Create and use vtkMath.arrayMin and vtkMath.arrayMax as suggested by: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply#Using_apply_and_built-in_functions Apply in Texture and PiecewiseGaussianWidget. This improves volume rendering performance by ~15%.
1 parent fa779a0 commit 47d4061

File tree

4 files changed

+45
-20
lines changed

4 files changed

+45
-20
lines changed

Sources/Common/Core/Math/api.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ Same as Math.min().
3434

3535
Same as Math.max().
3636

37-
### isPowerOfTwo(number) : Boolean
37+
### arrayMin(array)
3838

39-
NOT IMPLEMENTED
39+
Minimum of the array.
4040

41-
### nearestPowerOfTwo(number) : int
41+
### arrayMax(a, b)
4242

43-
NOT IMPLEMENTED
43+
Maximum of the array.
4444

4545
### factorial(n) : number
4646

Sources/Common/Core/Math/index.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const { vtkErrorMacro, vtkWarningMacro } = macro;
1212
let randomSeedValue = 0;
1313
const VTK_MAX_ROTATIONS = 20;
1414
const VTK_SMALL_NUMBER = 1.0e-12;
15+
const MAX_FUNCTION_ARGUMENTS = 32768;
1516

1617
function notImplemented(method) {
1718
return () => vtkErrorMacro(`vtkMath::${method} - NOT IMPLEMENTED`);
@@ -41,6 +42,33 @@ const Pi = () => Math.PI;
4142
const radiansFromDegrees = (deg) => deg / 180 * Math.PI;
4243
const degreesFromRadians = (rad) => rad * 180 / Math.PI;
4344
const { round, floor, ceil, min, max } = Math;
45+
46+
function arrayMin(arr) {
47+
let minValue = Infinity;
48+
for (let i = 0, len = arr.length; i < len; i += MAX_FUNCTION_ARGUMENTS) {
49+
const submin = Math.min.apply(
50+
null,
51+
arr.slice(i, Math.min(i + MAX_FUNCTION_ARGUMENTS, len))
52+
);
53+
minValue = Math.min(submin, minValue);
54+
}
55+
56+
return minValue;
57+
}
58+
59+
function arrayMax(arr) {
60+
let maxValue = -Infinity;
61+
for (let i = 0, len = arr.length; i < len; i += MAX_FUNCTION_ARGUMENTS) {
62+
const submax = Math.max.apply(
63+
null,
64+
arr.slice(i, Math.min(i + MAX_FUNCTION_ARGUMENTS, len))
65+
);
66+
maxValue = Math.max(submax, maxValue);
67+
}
68+
69+
return maxValue;
70+
}
71+
4472
const ceilLog2 = notImplemented('ceilLog2');
4573
const factorial = notImplemented('factorial');
4674

@@ -1993,6 +2021,8 @@ export default {
19932021
ceilLog2,
19942022
min,
19952023
max,
2024+
arrayMin,
2025+
arrayMax,
19962026
isPowerOfTwo,
19972027
nearestPowerOfTwo,
19982028
factorial,

Sources/Interaction/Widgets/PiecewiseGaussianWidget/index.js

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import macro from 'vtk.js/Sources/macro';
2+
import vtkMath from 'vtk.js/Sources/Common/Core/Math';
23

34
/* eslint-disable no-continue */
45

@@ -438,13 +439,8 @@ function vtkPiecewiseGaussianWidget(publicAPI, model) {
438439
numberOfBinsToSkip = 1
439440
) => {
440441
model.histogramArray = array;
441-
const size = array.length;
442-
let max = array[0];
443-
let min = array[0];
444-
for (let i = 1; i < size; i++) {
445-
max = Math.max(max, array[i]);
446-
min = Math.min(min, array[i]);
447-
}
442+
const max = vtkMath.arrayMax(array);
443+
const min = vtkMath.arrayMin(array);
448444

449445
const delta = max - min;
450446
model.dataRange = [min, max];

Sources/Rendering/OpenGL/Texture/index.js

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -930,12 +930,8 @@ function vtkOpenGLTexture(publicAPI, model) {
930930
const numPixelsIn = width * height * depth;
931931

932932
// compute min and max values
933-
let min = data[0];
934-
let max = data[0];
935-
for (let i = 0; i < numPixelsIn; ++i) {
936-
min = Math.min(min, data[i]);
937-
max = Math.max(max, data[i]);
938-
}
933+
const min = vtkMath.arrayMin(data);
934+
let max = vtkMath.arrayMax(data);
939935
if (min === max) {
940936
max = min + 1.0;
941937
}
@@ -1115,6 +1111,7 @@ function vtkOpenGLTexture(publicAPI, model) {
11151111
// have to compute the gradient to get the normal
11161112
// and magnitude
11171113
const tmpArray = new Float32Array(width * height * depth * 4);
1114+
const tmpMagArray = new Float32Array(width * height * depth);
11181115

11191116
let inPtr = 0;
11201117
let outPtr = 0;
@@ -1151,18 +1148,20 @@ function vtkOpenGLTexture(publicAPI, model) {
11511148
);
11521149

11531150
const mag = vec3.length(grad);
1154-
minMag = Math.min(mag, minMag);
1155-
maxMag = Math.max(mag, maxMag);
1156-
11571151
vec3.normalize(grad, grad);
11581152
tmpArray[outPtr++] = grad[0];
11591153
tmpArray[outPtr++] = grad[1];
11601154
tmpArray[outPtr++] = grad[2];
11611155
tmpArray[outPtr++] = mag;
1156+
tmpMagArray[inPtr] = mag;
11621157
inPtr++;
11631158
}
11641159
}
11651160
}
1161+
const arrayMinMag = vtkMath.arrayMin(tmpMagArray);
1162+
const arrayMaxMag = vtkMath.arrayMax(tmpMagArray);
1163+
minMag = Math.min(arrayMinMag, minMag);
1164+
maxMag = Math.max(arrayMaxMag, maxMag);
11661165

11671166
// store the information, we will need it later
11681167
model.volumeInfo = { min: minMag, max: maxMag };

0 commit comments

Comments
 (0)