Skip to content

Commit 8c5f66d

Browse files
authored
Merge pull request #4271 from plotly/streamtube-positions
Correct streamtube positions and colouring
2 parents 920f938 + 4af4984 commit 8c5f66d

17 files changed

+828
-74
lines changed

package-lock.json

+11-21
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373
"delaunay-triangulate": "^1.1.6",
7474
"es6-promise": "^3.0.2",
7575
"fast-isnumeric": "^1.1.3",
76-
"gl-cone3d": "^1.4.1",
76+
"gl-cone3d": "^1.5.0",
7777
"gl-contour2d": "^1.1.6",
7878
"gl-error3d": "^1.0.15",
7979
"gl-heatmap2d": "^1.0.5",
@@ -86,7 +86,7 @@
8686
"gl-scatter3d": "^1.2.2",
8787
"gl-select-box": "^1.0.3",
8888
"gl-spikes2d": "^1.0.2",
89-
"gl-streamtube3d": "^1.3.1",
89+
"gl-streamtube3d": "^1.4.0",
9090
"gl-surface3d": "^1.4.6",
9191
"gl-text": "^1.1.8",
9292
"glslify": "^7.0.0",

src/traces/streamtube/calc.js

+115-11
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88

99
'use strict';
1010

11+
var Lib = require('../../lib');
1112
var colorscaleCalc = require('../../components/colorscale/calc');
1213

1314
module.exports = function calc(gd, trace) {
14-
var i;
15+
var i, j, k;
1516

1617
var u = trace.u;
1718
var v = trace.v;
@@ -56,19 +57,114 @@ module.exports = function calc(gd, trace) {
5657
var zMax = -Infinity;
5758
var zMin = Infinity;
5859

59-
for(i = 0; i < len; i++) {
60-
var xx = x[i];
61-
xMax = Math.max(xMax, xx);
62-
xMin = Math.min(xMin, xx);
60+
var gridFill = '';
61+
var filledX;
62+
var filledY;
63+
var filledZ;
64+
var firstX;
65+
var firstY;
66+
var firstZ;
67+
if(len) {
68+
firstX = x[0];
69+
firstY = y[0];
70+
firstZ = z[0];
71+
}
6372

64-
var yy = y[i];
65-
yMax = Math.max(yMax, yy);
66-
yMin = Math.min(yMin, yy);
73+
for(i = 0; i < len; i++) {
74+
xMax = Math.max(xMax, x[i]);
75+
xMin = Math.min(xMin, x[i]);
76+
77+
yMax = Math.max(yMax, y[i]);
78+
yMin = Math.min(yMin, y[i]);
79+
80+
zMax = Math.max(zMax, z[i]);
81+
zMin = Math.min(zMin, z[i]);
82+
83+
if(!filledX && x[i] !== firstX) {
84+
filledX = true;
85+
gridFill += 'x';
86+
}
87+
if(!filledY && y[i] !== firstY) {
88+
filledY = true;
89+
gridFill += 'y';
90+
}
91+
if(!filledZ && z[i] !== firstZ) {
92+
filledZ = true;
93+
gridFill += 'z';
94+
}
95+
}
96+
// fill if not filled - case of having dimension(s) with one item
97+
if(!filledX) gridFill += 'x';
98+
if(!filledY) gridFill += 'y';
99+
if(!filledZ) gridFill += 'z';
100+
101+
var Xs = distinctVals(trace.x.slice(0, len));
102+
var Ys = distinctVals(trace.y.slice(0, len));
103+
var Zs = distinctVals(trace.z.slice(0, len));
104+
105+
gridFill = gridFill.replace('x', (x[0] > x[len - 1] ? '-' : '+') + 'x');
106+
gridFill = gridFill.replace('y', (y[0] > y[len - 1] ? '-' : '+') + 'y');
107+
gridFill = gridFill.replace('z', (z[0] > z[len - 1] ? '-' : '+') + 'z');
108+
109+
var empty = function() {
110+
len = 0;
111+
Xs = [];
112+
Ys = [];
113+
Zs = [];
114+
};
115+
116+
// Over-specified mesh case, this would error in tube2mesh
117+
if(!len || len < Xs.length * Ys.length * Zs.length) empty();
118+
119+
var getArray = function(c) { return c === 'x' ? x : c === 'y' ? y : z; };
120+
var getVals = function(c) { return c === 'x' ? Xs : c === 'y' ? Ys : Zs; };
121+
var getDir = function(c) { return (c[len - 1] < c[0]) ? -1 : 1; };
122+
123+
var arrK = getArray(gridFill[1]);
124+
var arrJ = getArray(gridFill[3]);
125+
var arrI = getArray(gridFill[5]);
126+
var nk = getVals(gridFill[1]).length;
127+
var nj = getVals(gridFill[3]).length;
128+
var ni = getVals(gridFill[5]).length;
129+
130+
var arbitrary = false;
131+
132+
var getIndex = function(_i, _j, _k) {
133+
return nk * (nj * _i + _j) + _k;
134+
};
135+
136+
var dirK = getDir(getArray(gridFill[1]));
137+
var dirJ = getDir(getArray(gridFill[3]));
138+
var dirI = getDir(getArray(gridFill[5]));
139+
140+
for(i = 0; i < ni - 1; i++) {
141+
for(j = 0; j < nj - 1; j++) {
142+
for(k = 0; k < nk - 1; k++) {
143+
var q000 = getIndex(i, j, k);
144+
var q001 = getIndex(i, j, k + 1);
145+
var q010 = getIndex(i, j + 1, k);
146+
var q100 = getIndex(i + 1, j, k);
147+
148+
if(
149+
!(arrK[q000] * dirK < arrK[q001] * dirK) ||
150+
!(arrJ[q000] * dirJ < arrJ[q010] * dirJ) ||
151+
!(arrI[q000] * dirI < arrI[q100] * dirI)
152+
) {
153+
arbitrary = true;
154+
}
155+
156+
if(arbitrary) break;
157+
}
158+
if(arbitrary) break;
159+
}
160+
if(arbitrary) break;
161+
}
67162

68-
var zz = z[i];
69-
zMax = Math.max(zMax, zz);
70-
zMin = Math.min(zMin, zz);
163+
if(arbitrary) {
164+
Lib.warn('Encountered arbitrary coordinates! Unable to input data grid.');
165+
empty();
71166
}
167+
72168
for(i = 0; i < slen; i++) {
73169
var sx = startx[i];
74170
xMax = Math.max(xMax, sx);
@@ -89,4 +185,12 @@ module.exports = function calc(gd, trace) {
89185
trace._xbnds = [xMin, xMax];
90186
trace._ybnds = [yMin, yMax];
91187
trace._zbnds = [zMin, zMax];
188+
trace._Xs = Xs;
189+
trace._Ys = Ys;
190+
trace._Zs = Zs;
191+
trace._gridFill = gridFill;
92192
};
193+
194+
function distinctVals(col) {
195+
return Lib.distinctVals(col).vals;
196+
}

src/traces/streamtube/convert.js

+9-13
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,6 @@ proto.handlePick = function(selection) {
6262
}
6363
};
6464

65-
function distinctVals(col) {
66-
return Lib.distinctVals(col).vals;
67-
}
68-
6965
function getDfltStartingPositions(vec) {
7066
var len = vec.length;
7167
var s;
@@ -108,20 +104,20 @@ function convert(scene, trace) {
108104
len
109105
);
110106

111-
var valsx = distinctVals(trace.x.slice(0, len));
112-
var valsy = distinctVals(trace.y.slice(0, len));
113-
var valsz = distinctVals(trace.z.slice(0, len));
114-
115107
// Over-specified mesh case, this would error in tube2mesh
116-
if(valsx.length * valsy.length * valsz.length > len) {
117-
return {positions: [], cells: []};
108+
if(!len) {
109+
return {
110+
positions: [],
111+
cells: []
112+
};
118113
}
119114

120-
var meshx = toDataCoords(valsx, 'xaxis');
121-
var meshy = toDataCoords(valsy, 'yaxis');
122-
var meshz = toDataCoords(valsz, 'zaxis');
115+
var meshx = toDataCoords(trace._Xs, 'xaxis');
116+
var meshy = toDataCoords(trace._Ys, 'yaxis');
117+
var meshz = toDataCoords(trace._Zs, 'zaxis');
123118

124119
tubeOpts.meshgrid = [meshx, meshy, meshz];
120+
tubeOpts.gridFill = trace._gridFill;
125121

126122
var slen = trace._slen;
127123
if(slen) {
-108 Bytes
Loading
Loading
Loading
Loading
-13.2 KB
Loading
897 Bytes
Loading
-944 Bytes
Loading
-7.33 KB
Loading
-3.63 KB
Loading
Loading

0 commit comments

Comments
 (0)