Skip to content

Commit 5a95dab

Browse files
committed
Apply streamtube processGrid in isosurface and volume
- add image tests for various grid fill orders - add jasmine tests for various grid fill orders and data types
1 parent d015b57 commit 5a95dab

File tree

8 files changed

+778
-16
lines changed

8 files changed

+778
-16
lines changed

src/traces/isosurface/calc.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,28 @@
99
'use strict';
1010

1111
var colorscaleCalc = require('../../components/colorscale/calc');
12+
var processGrid = require('../streamtube/calc').processGrid;
1213

1314
module.exports = function calc(gd, trace) {
1415
trace._len = Math.min(trace.x.length, trace.y.length, trace.z.length, trace.value.length);
1516

17+
var grid = processGrid(trace);
18+
trace._gridFill = grid.fill;
19+
trace._Xs = grid.Xs;
20+
trace._Ys = grid.Ys;
21+
trace._Zs = grid.Zs;
22+
trace._len = grid.len;
23+
1624
var min = Infinity;
1725
var max = -Infinity;
18-
var len = trace.value.length;
19-
for(var i = 0; i < len; i++) {
26+
for(var i = 0; i < trace._len; i++) {
2027
var v = trace.value[i];
2128
min = Math.min(min, v);
2229
max = Math.max(max, v);
2330
}
2431

2532
trace._minValues = min;
2633
trace._maxValues = max;
27-
2834
trace._vMin = (trace.isomin === undefined || trace.isomin === null) ? min : trace.isomin;
2935
trace._vMax = (trace.isomax === undefined || trace.isomin === null) ? max : trace.isomax;
3036

src/traces/isosurface/convert.js

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,11 @@
99
'use strict';
1010

1111
var createMesh = require('gl-mesh3d');
12-
13-
var Lib = require('../../lib');
14-
1512
var parseColorScale = require('../../lib/gl_format_color').parseColorScale;
1613
var str2RgbaArray = require('../../lib/str2rgbarray');
1714
var extractOpts = require('../../components/colorscale').extractOpts;
1815
var zip3 = require('../../plots/gl3d/zip3');
1916

20-
function distinctVals(col) {
21-
return Lib.distinctVals(col).vals;
22-
}
23-
2417
var findNearestOnAxis = function(w, arr) {
2518
for(var q = arr.length - 1; q > 0; q--) {
2619
var min = Math.min(arr[q], arr[q - 1]);
@@ -136,6 +129,8 @@ proto.dispose = function() {
136129
this.mesh.dispose();
137130
};
138131

132+
var GRID_TYPES = ['xyz', 'xzy', 'yxz', 'yzx', 'zxy', 'zyx'];
133+
139134
function generateIsoMeshes(data) {
140135
data._i = [];
141136
data._j = [];
@@ -154,17 +149,32 @@ function generateIsoMeshes(data) {
154149
var numVertices;
155150
var beginVertextLength;
156151

157-
var Xs = distinctVals(data.x.slice(0, data._len));
158-
var Ys = distinctVals(data.y.slice(0, data._len));
159-
var Zs = distinctVals(data.z.slice(0, data._len));
152+
var Xs = data._Xs;
153+
var Ys = data._Ys;
154+
var Zs = data._Zs;
160155

161156
var width = Xs.length;
162157
var height = Ys.length;
163158
var depth = Zs.length;
164159

165-
function getIndex(i, j, k) {
166-
return k + depth * j + depth * height * i;
167-
}
160+
var filled = GRID_TYPES.indexOf(data._gridFill.replace(/-/g, '').replace(/\+/g, ''));
161+
162+
var getIndex = function(i, j, k) {
163+
switch(filled) {
164+
case 5: // 'zyx'
165+
return k + depth * j + depth * height * i;
166+
case 4: // 'zxy'
167+
return k + depth * i + depth * width * j;
168+
case 3: // 'yzx'
169+
return j + height * k + height * depth * i;
170+
case 2: // 'yxz'
171+
return j + height * i + height * width * k;
172+
case 1: // 'xzy'
173+
return i + width * k + width * depth * j;
174+
default: // case 0: // 'xyz'
175+
return i + width * j + width * height * k;
176+
}
177+
};
168178

169179
var minValues = data._minValues;
170180
var maxValues = data._maxValues;
Loading
Loading

test/image/mocks/gl3d_directions-isosurface1.json

Lines changed: 227 additions & 0 deletions
Large diffs are not rendered by default.

test/image/mocks/gl3d_directions-isosurface2.json

Lines changed: 227 additions & 0 deletions
Large diffs are not rendered by default.

test/jasmine/tests/isosurface_test.js

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
var Plotly = require('@lib');
2+
var Lib = require('@src/lib');
23

34
var supplyAllDefaults = require('../assets/supply_defaults');
45
var createGraphDiv = require('../assets/create_graph_div');
@@ -391,3 +392,148 @@ describe('Test isosurface', function() {
391392
});
392393
});
393394
});
395+
396+
describe('Test isosurface grid', function() {
397+
var gd;
398+
399+
beforeEach(function() {
400+
gd = createGraphDiv();
401+
});
402+
403+
afterEach(function() {
404+
Plotly.purge(gd);
405+
destroyGraphDiv();
406+
});
407+
408+
[ // list of directions
409+
'number',
410+
'string',
411+
'typedArray'
412+
].forEach(function(format) {
413+
[ // list of directions
414+
[-1, -1, -1],
415+
[-1, -1, 1],
416+
[-1, 1, -1],
417+
[1, -1, -1],
418+
[1, 1, -1],
419+
[1, -1, 1],
420+
[-1, 1, 1],
421+
[1, 1, 1]
422+
].forEach(function(dir) {
423+
it('@gl should work with grid steps: ' + dir + ' and values in ' + format + ' format.', function(done) {
424+
var x = [];
425+
var y = [];
426+
var z = [];
427+
var v = [];
428+
429+
for(var i = 0; i < 3; i++) {
430+
for(var j = 0; j < 4; j++) {
431+
for(var k = 0; k < 5; k++) {
432+
var newX = i * dir[0];
433+
var newY = j * dir[1];
434+
var newZ = k * dir[2];
435+
var newV = (
436+
newX * newX +
437+
newY * newY +
438+
newZ * newZ
439+
);
440+
441+
if(format === 'string') {
442+
newV = String(newV);
443+
newX = String(newX);
444+
newY = String(newY);
445+
newZ = String(newZ);
446+
}
447+
448+
v.push(newV);
449+
x.push(newX);
450+
y.push(newY);
451+
z.push(newZ);
452+
}
453+
}
454+
}
455+
456+
if(format === 'typedArray') {
457+
v = new Int32Array(v);
458+
x = new Float32Array(x);
459+
y = new Float32Array(y);
460+
z = new Float64Array(z);
461+
}
462+
463+
var fig = {
464+
data: [{
465+
type: 'isosurface',
466+
x: x,
467+
y: y,
468+
z: z,
469+
value: v
470+
}]
471+
};
472+
473+
function _assert(msg, exp) {
474+
var scene = gd._fullLayout.scene._scene;
475+
var objs = scene.glplot.objects;
476+
expect(objs.length).toBe(1, 'one gl-vis object - ' + msg);
477+
expect(exp.positionsLength).toBe(objs[0].positions.length, 'positions length - ' + msg);
478+
expect(exp.cellsLength).toBe(objs[0].cells.length, 'cells length - ' + msg);
479+
}
480+
481+
Plotly.plot(gd, fig).then(function() {
482+
_assert('lengths', {
483+
positionsLength: 372,
484+
cellsLength: 104
485+
});
486+
})
487+
.catch(failTest)
488+
.then(done);
489+
});
490+
});
491+
});
492+
493+
it('@gl should return blank mesh grid if encountered arbitrary coordinates', function(done) {
494+
var x = [];
495+
var y = [];
496+
var z = [];
497+
var v = [];
498+
499+
Lib.seedPseudoRandom();
500+
501+
for(var n = 0; n < 1000; n++) {
502+
x.push((10 * Lib.pseudoRandom()) | 0);
503+
y.push((10 * Lib.pseudoRandom()) | 0);
504+
z.push((10 * Lib.pseudoRandom()) | 0);
505+
v.push((10 * Lib.pseudoRandom()) | 0);
506+
}
507+
508+
var fig = {
509+
data: [{
510+
type: 'isosurface',
511+
x: x,
512+
y: y,
513+
z: z,
514+
value: v
515+
}]
516+
};
517+
518+
function _assert(msg, exp) {
519+
var scene = gd._fullLayout.scene._scene;
520+
var objs = scene.glplot.objects;
521+
expect(objs.length).toBe(1, 'one gl-vis object - ' + msg);
522+
expect(exp.positionsLength).toBe(objs[0].positions.length, 'positions length - ' + msg);
523+
expect(exp.cellsLength).toBe(objs[0].cells.length, 'cells length - ' + msg);
524+
}
525+
526+
spyOn(Lib, 'warn');
527+
528+
Plotly.plot(gd, fig).then(function() {
529+
_assert('arbitrary coordinates', {
530+
positionsLength: 0,
531+
cellsLength: 0
532+
});
533+
}).then(function() {
534+
expect(Lib.warn).toHaveBeenCalledWith('Encountered arbitrary coordinates! Unable to input data grid.');
535+
})
536+
.catch(failTest)
537+
.then(done);
538+
});
539+
});

0 commit comments

Comments
 (0)