Skip to content

Commit ba74cac

Browse files
authored
Merge pull request #501 from Kitware/fix-mag-computation
fix(DataArray): Add magnitude range computation
2 parents 85622e1 + 99c38a8 commit ba74cac

File tree

3 files changed

+105
-23
lines changed

3 files changed

+105
-23
lines changed

Sources/Common/Core/DataArray/index.js

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,61 @@ import macro from 'vtk.js/Sources/macro';
22
import Constants from 'vtk.js/Sources/Common/Core/DataArray/Constants';
33

44
const { DefaultDataType } = Constants;
5-
const { vtkErrorMacro } = macro;
65
const TUPLE_HOLDER = [];
76

87
// ----------------------------------------------------------------------------
98
// Global methods
109
// ----------------------------------------------------------------------------
1110

12-
function computeRange(values, component = 0, tuple = 1) {
13-
const range = { min: Number.MAX_VALUE, max: -Number.MAX_VALUE };
11+
function createRangeHelper() {
12+
let min = Number.MAX_VALUE;
13+
let max = -Number.MAX_VALUE;
14+
let count = 0;
15+
let sum = 0;
16+
17+
return {
18+
add(value) {
19+
if (min > value) {
20+
min = value;
21+
}
22+
if (max < value) {
23+
max = value;
24+
}
25+
count++;
26+
sum += value;
27+
},
28+
get() {
29+
return { min, max, count, sum, mean: sum / count };
30+
},
31+
getRange() {
32+
return { min, max };
33+
},
34+
};
35+
}
36+
37+
function computeRange(values, component = 0, numberOfComponents = 1) {
38+
const helper = createRangeHelper();
39+
const size = values.length;
40+
let value = 0;
1441

1542
if (component < 0) {
1643
// Compute magnitude
17-
vtkErrorMacro('vtkDataArray: Compute magnitude - NOT IMPLEMENTED');
18-
return range;
44+
for (let i = 0; i < size; i += numberOfComponents) {
45+
value = 0;
46+
for (let j = 0; j < numberOfComponents; j++) {
47+
value += values[i + j] * values[i + j];
48+
}
49+
value **= 0.5;
50+
helper.add(value);
51+
}
52+
return helper.getRange();
1953
}
2054

21-
const size = values.length;
22-
for (let i = component; i < size; i += tuple) {
23-
const value = values[i];
24-
if (range.min > value) {
25-
range.min = value;
26-
}
27-
if (range.max < value) {
28-
range.max = value;
29-
}
55+
for (let i = component; i < size; i += numberOfComponents) {
56+
helper.add(values[i]);
3057
}
3158

32-
return range;
59+
return helper.getRange();
3360
}
3461

3562
function ensureRangeSize(rangeArray, size = 0) {
@@ -55,6 +82,7 @@ function getDataType(typedArray) {
5582
export const STATIC = {
5683
computeRange,
5784
getDataType,
85+
createRangeHelper,
5886
};
5987

6088
// ----------------------------------------------------------------------------
@@ -93,7 +121,7 @@ function vtkDataArray(publicAPI, model) {
93121

94122
publicAPI.getData = () => model.values;
95123

96-
publicAPI.getRange = (componentIndex = 0) => {
124+
publicAPI.getRange = (componentIndex = -1) => {
97125
const rangeIdx =
98126
componentIndex < 0 ? model.numberOfComponents : componentIndex;
99127
let range = null;

Sources/Interaction/Widgets/PiecewiseGaussianWidget/index.js

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,30 @@ function computeOpacities(gaussians, sampling = 256) {
127127

128128
// ----------------------------------------------------------------------------
129129

130+
function applyGaussianToPiecewiseFunction(
131+
gaussians,
132+
sampling,
133+
rangeToUse,
134+
piecewiseFunction
135+
) {
136+
const opacities = computeOpacities(gaussians, sampling);
137+
const nodes = [];
138+
const delta = (rangeToUse[1] - rangeToUse[0]) / (opacities.length - 1);
139+
const midpoint = 0.5;
140+
const sharpness = 0;
141+
for (let index = 0; index < opacities.length; index++) {
142+
const x = rangeToUse[0] + delta * index;
143+
const y = opacities[index];
144+
nodes.push({ x, y, midpoint, sharpness });
145+
}
146+
147+
piecewiseFunction.removeAllPoints();
148+
piecewiseFunction.set({ nodes }, true);
149+
piecewiseFunction.sortAndUpdateRange();
150+
}
151+
152+
// ----------------------------------------------------------------------------
153+
130154
function drawChart(
131155
ctx,
132156
area,
@@ -332,12 +356,13 @@ function listenerSelector(condition, ok, ko) {
332356
// ----------------------------------------------------------------------------
333357

334358
export const STATIC = {
359+
applyGaussianToPiecewiseFunction,
335360
computeOpacities,
361+
createListener,
336362
drawChart,
337-
normalizeCoordinates,
338363
findGaussian,
339-
createListener,
340364
listenerSelector,
365+
normalizeCoordinates,
341366
};
342367

343368
// ----------------------------------------------------------------------------

Sources/macro.js

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,7 @@ export function debounce(func, wait, immediate) {
886886
// getProxySection() => List of properties for UI generation
887887
// ----------------------------------------------------------------------------
888888
let nextProxyId = 1;
889+
const ROOT_GROUP_NAME = '__root__';
889890

890891
export function proxy(publicAPI, model, sectionName, uiDescription = []) {
891892
const parentDelete = publicAPI.delete;
@@ -894,9 +895,30 @@ export function proxy(publicAPI, model, sectionName, uiDescription = []) {
894895
model.proxyId = `${nextProxyId++}`;
895896
publicAPI.getProxyId = () => model.proxyId;
896897

898+
// group properties
899+
const groupChildrenNames = {};
900+
function registerProperties(descriptionList, currentGroupName) {
901+
if (!groupChildrenNames[currentGroupName]) {
902+
groupChildrenNames[currentGroupName] = [];
903+
}
904+
const childrenNames = groupChildrenNames[currentGroupName];
905+
906+
for (let i = 0; i < descriptionList.length; i++) {
907+
childrenNames.push(descriptionList[i].name);
908+
909+
if (descriptionList[i].children && descriptionList[i].children.length) {
910+
registerProperties(
911+
descriptionList[i].children,
912+
descriptionList[i].name
913+
);
914+
}
915+
}
916+
}
917+
registerProperties(uiDescription, ROOT_GROUP_NAME);
918+
897919
// list
898-
const propertyNames = uiDescription.map((p) => p.name);
899-
publicAPI.listProxyProperties = () => propertyNames;
920+
publicAPI.listProxyProperties = (gName = ROOT_GROUP_NAME) =>
921+
groupChildrenNames[gName];
900922

901923
// ui handling
902924
const ui = uiDescription.map((i) => Object.assign({}, i));
@@ -981,13 +1003,20 @@ export function proxy(publicAPI, model, sectionName, uiDescription = []) {
9811003
};
9821004

9831005
// extract values
984-
function getProperties() {
1006+
function getProperties(groupName = ROOT_GROUP_NAME) {
9851007
const values = [];
9861008
const id = model.proxyId;
1009+
const propertyNames = publicAPI.listProxyProperties(groupName) || [];
9871010
for (let i = 0; i < propertyNames.length; i++) {
9881011
const name = propertyNames[i];
989-
const value = publicAPI[`get${capitalize(name)}`]();
990-
values.push({ id, name, value });
1012+
const method = publicAPI[`get${capitalize(name)}`];
1013+
const value = method ? method() : undefined;
1014+
const prop = { id, name, value };
1015+
const children = getProperties(name);
1016+
if (children.length) {
1017+
prop.children = children;
1018+
}
1019+
values.push(prop);
9911020
}
9921021
return values;
9931022
}

0 commit comments

Comments
 (0)