Skip to content

Commit 088a2c7

Browse files
authored
Merge pull request #3299 from plotly/issue-0179
Issue 0179
2 parents 174458a + 144768c commit 088a2c7

File tree

8 files changed

+149
-89
lines changed

8 files changed

+149
-89
lines changed

package-lock.json

Lines changed: 2 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
"gl-select-box": "^1.0.2",
8585
"gl-spikes2d": "^1.0.1",
8686
"gl-streamtube3d": "^1.1.1",
87-
"gl-surface3d": "^1.3.8",
87+
"gl-surface3d": "git://github.com/gl-vis/gl-surface3d.git#2a1728fae4d9ee30e0c34e945859234cc489e32a",
8888
"gl-text": "^1.1.6",
8989
"glslify": "^6.3.1",
9090
"has-hover": "^1.0.1",

src/plots/gl3d/scene.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,11 @@ function computeTraceBounds(scene, trace, bounds) {
380380
}
381381
}
382382
}
383+
384+
if(trace.type === 'surface') {
385+
bounds[0][d] += trace._objectOffset[d];
386+
bounds[1][d] += trace._objectOffset[d];
387+
}
383388
}
384389
}
385390

src/traces/surface/convert.js

Lines changed: 139 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -25,59 +25,81 @@ function SurfaceTrace(scene, surface, uid) {
2525
this.surface = surface;
2626
this.data = null;
2727
this.showContour = [false, false, false];
28+
this.minValues = [Infinity, Infinity, Infinity];
29+
this.maxValues = [-Infinity, -Infinity, -Infinity];
30+
this.midValues = [0, 0, 0];
2831
this.dataScaleX = 1.0;
2932
this.dataScaleY = 1.0;
30-
this.refineData = true; // this could also be set by user...
33+
this.refineData = true;
3134
}
3235

3336
var proto = SurfaceTrace.prototype;
3437

35-
proto.getXat = function(a, b) {
36-
return (!isArrayOrTypedArray(this.data.x)) ?
37-
a :
38-
(isArrayOrTypedArray(this.data.x[0])) ?
39-
this.data.x[b][a] :
40-
this.data.x[a];
38+
proto.getXat = function(a, b, calendar, axis) {
39+
var v = (
40+
(!isArrayOrTypedArray(this.data.x)) ?
41+
a :
42+
(isArrayOrTypedArray(this.data.x[0])) ?
43+
this.data.x[b][a] :
44+
this.data.x[a]
45+
);
46+
47+
return (calendar === undefined) ? v : axis.d2l(v, 0, calendar);
4148
};
4249

43-
proto.getYat = function(a, b) {
44-
return (!isArrayOrTypedArray(this.data.y)) ?
45-
b :
46-
(isArrayOrTypedArray(this.data.y[0])) ?
47-
this.data.y[b][a] :
48-
this.data.y[b];
50+
proto.getYat = function(a, b, calendar, axis) {
51+
var v = (
52+
(!isArrayOrTypedArray(this.data.y)) ?
53+
b :
54+
(isArrayOrTypedArray(this.data.y[0])) ?
55+
this.data.y[b][a] :
56+
this.data.y[b]
57+
);
58+
59+
return (calendar === undefined) ? v : axis.d2l(v, 0, calendar);
60+
};
61+
62+
proto.getZat = function(a, b, calendar, axis) {
63+
var v = (
64+
this.data.z[b][a]
65+
);
66+
67+
return (calendar === undefined) ? v : axis.d2l(v, 0, calendar);
4968
};
5069

5170
proto.handlePick = function(selection) {
5271
if(selection.object === this.surface) {
53-
var selectIndex = selection.index = [
54-
Math.min(
55-
Math.floor(selection.data.index[0] / this.dataScaleX - 1),
56-
this.data.z[0].length - 1
57-
),
58-
Math.min(
59-
Math.floor(selection.data.index[1] / this.dataScaleY - 1),
60-
this.data.z.length - 1
61-
)
62-
];
63-
var traceCoordinate = [0, 0, 0];
6472

65-
traceCoordinate[0] = this.getXat(selectIndex[0], selectIndex[1]);
66-
traceCoordinate[1] = this.getYat(selectIndex[0], selectIndex[1]);
73+
var xRatio = (selection.data.index[0] - 1) / this.dataScaleX - 1;
74+
var yRatio = (selection.data.index[1] - 1) / this.dataScaleY - 1;
75+
76+
var j = Math.max(Math.min(Math.round(xRatio), this.data._xlength - 1), 0);
77+
var k = Math.max(Math.min(Math.round(yRatio), this.data._ylength - 1), 0);
6778

68-
traceCoordinate[2] = this.data.z[selectIndex[1]][selectIndex[0]];
69-
selection.traceCoordinate = traceCoordinate;
79+
selection.index = [j, k];
80+
81+
selection.traceCoordinate = [
82+
this.getXat(j, k),
83+
this.getYat(j, k),
84+
this.getZat(j, k)
85+
];
7086

71-
var sceneLayout = this.scene.fullSceneLayout;
7287
selection.dataCoordinate = [
73-
sceneLayout.xaxis.d2l(traceCoordinate[0], 0, this.data.xcalendar) * this.scene.dataScale[0],
74-
sceneLayout.yaxis.d2l(traceCoordinate[1], 0, this.data.ycalendar) * this.scene.dataScale[1],
75-
sceneLayout.zaxis.d2l(traceCoordinate[2], 0, this.data.zcalendar) * this.scene.dataScale[2]
88+
this.getXat(j, k, this.data.xcalendar, this.scene.fullSceneLayout.xaxis),
89+
this.getYat(j, k, this.data.ycalendar, this.scene.fullSceneLayout.yaxis),
90+
this.getZat(j, k, this.data.zcalendar, this.scene.fullSceneLayout.zaxis)
7691
];
7792

93+
for(var i = 0; i < 3; i++) {
94+
var v = selection.dataCoordinate[i];
95+
if(v !== null && v !== undefined) {
96+
selection.dataCoordinate[i] *= this.scene.dataScale[i];
97+
}
98+
}
99+
78100
var text = this.data.text;
79-
if(Array.isArray(text) && text[selectIndex[1]] && text[selectIndex[1]][selectIndex[0]] !== undefined) {
80-
selection.textLabel = text[selectIndex[1]][selectIndex[0]];
101+
if(Array.isArray(text) && text[k] && text[k][j] !== undefined) {
102+
selection.textLabel = text[k][j];
81103
} else if(text) {
82104
selection.textLabel = text;
83105
} else {
@@ -318,28 +340,14 @@ proto.setContourLevels = function() {
318340
};
319341

320342
proto.update = function(data) {
321-
var i,
322-
scene = this.scene,
343+
var scene = this.scene,
323344
sceneLayout = scene.fullSceneLayout,
324345
surface = this.surface,
325346
alpha = data.opacity,
326347
colormap = parseColorScale(data.colorscale, alpha),
327-
z = data.z,
328-
x = data.x,
329-
y = data.y,
330-
xaxis = sceneLayout.xaxis,
331-
yaxis = sceneLayout.yaxis,
332-
zaxis = sceneLayout.zaxis,
333348
scaleFactor = scene.dataScale,
334-
xlen = z[0].length,
349+
xlen = data._xlength,
335350
ylen = data._ylength,
336-
coords = [
337-
ndarray(new Float32Array(xlen * ylen), [xlen, ylen]),
338-
ndarray(new Float32Array(xlen * ylen), [xlen, ylen]),
339-
ndarray(new Float32Array(xlen * ylen), [xlen, ylen])
340-
],
341-
xc = coords[0],
342-
yc = coords[1],
343351
contourLevels = scene.contourLevels;
344352

345353
// Save data
@@ -353,46 +361,87 @@ proto.update = function(data) {
353361
* which is the transpose of 'gl-surface-plot'.
354362
*/
355363

356-
var xcalendar = data.xcalendar,
357-
ycalendar = data.ycalendar,
358-
zcalendar = data.zcalendar;
364+
var i, j, k, v;
365+
var rawCoords = [];
366+
for(i = 0; i < 3; i++) {
367+
rawCoords[i] = [];
368+
for(j = 0; j < xlen; j++) {
369+
rawCoords[i][j] = [];
370+
/*
371+
for(k = 0; k < ylen; k++) {
372+
rawCoords[i][j][k] = undefined;
373+
}
374+
*/
375+
}
376+
}
359377

360-
fill(coords[2], function(row, col) {
361-
return zaxis.d2l(z[col][row], 0, zcalendar) * scaleFactor[2];
362-
});
378+
// coords x, y & z
379+
for(j = 0; j < xlen; j++) {
380+
for(k = 0; k < ylen; k++) {
381+
rawCoords[0][j][k] = this.getXat(j, k, data.xcalendar, sceneLayout.xaxis);
382+
rawCoords[1][j][k] = this.getYat(j, k, data.ycalendar, sceneLayout.yaxis);
383+
rawCoords[2][j][k] = this.getZat(j, k, data.zcalendar, sceneLayout.zaxis);
384+
}
385+
}
363386

364-
// coords x
365-
if(!isArrayOrTypedArray(x)) {
366-
fill(xc, function(row) {
367-
return xaxis.d2l(row, 0, xcalendar) * scaleFactor[0];
368-
});
369-
} else if(isArrayOrTypedArray(x[0])) {
370-
fill(xc, function(row, col) {
371-
return xaxis.d2l(x[col][row], 0, xcalendar) * scaleFactor[0];
372-
});
373-
} else {
374-
// ticks x
375-
fill(xc, function(row) {
376-
return xaxis.d2l(x[row], 0, xcalendar) * scaleFactor[0];
377-
});
387+
// Note: log axes are not defined in surfaces yet.
388+
// but they could be defined here...
389+
390+
for(i = 0; i < 3; i++) {
391+
for(j = 0; j < xlen; j++) {
392+
for(k = 0; k < ylen; k++) {
393+
v = rawCoords[i][j][k];
394+
if(v === null || v === undefined) {
395+
rawCoords[i][j][k] = NaN;
396+
} else {
397+
v = rawCoords[i][j][k] *= scaleFactor[i];
398+
}
399+
}
400+
}
378401
}
379402

380-
// coords y
381-
if(!isArrayOrTypedArray(x)) {
382-
fill(yc, function(row, col) {
383-
return yaxis.d2l(col, 0, xcalendar) * scaleFactor[1];
384-
});
385-
} else if(isArrayOrTypedArray(y[0])) {
386-
fill(yc, function(row, col) {
387-
return yaxis.d2l(y[col][row], 0, ycalendar) * scaleFactor[1];
388-
});
389-
} else {
390-
// ticks y
391-
fill(yc, function(row, col) {
392-
return yaxis.d2l(y[col], 0, ycalendar) * scaleFactor[1];
393-
});
403+
for(i = 0; i < 3; i++) {
404+
for(j = 0; j < xlen; j++) {
405+
for(k = 0; k < ylen; k++) {
406+
v = rawCoords[i][j][k];
407+
if(v !== null && v !== undefined) {
408+
if(this.minValues[i] > v) {
409+
this.minValues[i] = v;
410+
}
411+
if(this.maxValues[i] < v) {
412+
this.maxValues[i] = v;
413+
}
414+
}
415+
}
416+
}
417+
}
418+
419+
for(i = 0; i < 3; i++) {
420+
data._objectOffset[i] = this.midValues[i] = 0.5 * (this.minValues[i] + this.maxValues[i]);
421+
}
422+
423+
for(i = 0; i < 3; i++) {
424+
for(j = 0; j < xlen; j++) {
425+
for(k = 0; k < ylen; k++) {
426+
v = rawCoords[i][j][k];
427+
if(v !== null && v !== undefined) {
428+
rawCoords[i][j][k] -= this.midValues[i];
429+
}
430+
}
431+
}
394432
}
395433

434+
// convert processed raw data to Float32 matrices
435+
var coords = [
436+
ndarray(new Float32Array(xlen * ylen), [xlen, ylen]),
437+
ndarray(new Float32Array(xlen * ylen), [xlen, ylen]),
438+
ndarray(new Float32Array(xlen * ylen), [xlen, ylen])
439+
];
440+
fill(coords[0], function(row, col) { return rawCoords[0][row][col]; });
441+
fill(coords[1], function(row, col) { return rawCoords[1][row][col]; });
442+
fill(coords[2], function(row, col) { return rawCoords[2][row][col]; });
443+
rawCoords = []; // free memory
444+
396445
var params = {
397446
colormap: colormap,
398447
levels: [[], [], []],
@@ -491,8 +540,13 @@ proto.update = function(data) {
491540
params.vertexColor = true;
492541
}
493542

494-
params.coords = coords;
543+
params.objectOffset = [
544+
data._objectOffset[0],
545+
data._objectOffset[1],
546+
data._objectOffset[2]
547+
];
495548

549+
params.coords = coords;
496550
surface.update(params);
497551

498552
surface.visible = data.visible;

src/traces/surface/defaults.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
3535
traceOut._xlength = (Array.isArray(x) && Lib.isArrayOrTypedArray(x[0])) ? z.length : z[0].length;
3636
traceOut._ylength = z.length;
3737

38+
traceOut._objectOffset = [0, 0, 0];
39+
3840
var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults');
3941
handleCalendarDefaults(traceIn, traceOut, ['x', 'y', 'z'], layout);
4042

-350 Bytes
Loading

test/image/baselines/gl3d_ribbons.png

8.75 KB
Loading
100 Bytes
Loading

0 commit comments

Comments
 (0)