Skip to content

Commit 5208bb3

Browse files
committed
Merge pull request #153 from plotly/surface-zmin-zmax
Make surface handle zmin/zmax [fixes #86]
2 parents 6ba33f5 + e3928e3 commit 5208bb3

15 files changed

+132
-114
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
"gl-scatter3d": "^1.0.4",
6464
"gl-select-box": "^1.0.1",
6565
"gl-spikes2d": "^1.0.1",
66-
"gl-surface3d": "^1.0.6",
66+
"gl-surface3d": "^1.1.0",
6767
"mouse-change": "^1.1.1",
6868
"mouse-wheel": "^1.0.2",
6969
"ndarray": "^1.0.16",

src/traces/surface/convert.js

+128-112
Original file line numberDiff line numberDiff line change
@@ -20,58 +20,68 @@ var str2RgbaArray = require('../../lib/str2rgbarray');
2020

2121
var MIN_RESOLUTION = 128;
2222

23+
2324
function SurfaceTrace(scene, surface, uid) {
24-
this.scene = scene;
25-
this.uid = uid;
26-
this.surface = surface;
27-
this.data = null;
28-
this.showContour = [false,false,false];
29-
this.dataScale = 1.0;
25+
this.scene = scene;
26+
this.uid = uid;
27+
this.surface = surface;
28+
this.data = null;
29+
this.showContour = [false, false, false];
30+
this.dataScale = 1.0;
3031
}
3132

3233
var proto = SurfaceTrace.prototype;
3334

3435
proto.handlePick = function(selection) {
35-
if(selection.object === this.surface) {
36-
var selectIndex = [
37-
Math.min(Math.round(selection.data.index[0]/this.dataScale-1)|0, this.data.z[0].length-1),
38-
Math.min(Math.round(selection.data.index[1]/this.dataScale-1)|0, this.data.z.length-1) ];
39-
var traceCoordinate = [0,0,0];
40-
if(Array.isArray(this.data.x[0])) {
41-
traceCoordinate[0] = this.data.x[selectIndex[1]][selectIndex[0]];
42-
} else {
43-
traceCoordinate[0] = this.data.x[selectIndex[0]];
44-
}
45-
if(Array.isArray(this.data.y[0])) {
46-
traceCoordinate[1] = this.data.y[selectIndex[1]][selectIndex[0]];
47-
} else {
48-
traceCoordinate[1] = this.data.y[selectIndex[1]];
49-
}
50-
traceCoordinate[2] = this.data.z[selectIndex[1]][selectIndex[0]];
51-
selection.traceCoordinate = traceCoordinate;
52-
53-
var sceneLayout = this.scene.fullSceneLayout;
54-
selection.dataCoordinate = [
55-
sceneLayout.xaxis.d2l(traceCoordinate[0])*this.scene.dataScale[0],
56-
sceneLayout.yaxis.d2l(traceCoordinate[1])*this.scene.dataScale[1],
57-
sceneLayout.zaxis.d2l(traceCoordinate[2])*this.scene.dataScale[2]
58-
];
59-
60-
var text = this.data.text;
61-
if(text && text[selectIndex[1]] && text[selectIndex[1]][selectIndex[0]]!==undefined) {
62-
selection.textLabel = text[selectIndex[1]][selectIndex[0]];
63-
}
64-
else selection.textLabel = '';
36+
if(selection.object === this.surface) {
37+
var selectIndex = [
38+
Math.min(
39+
Math.round(selection.data.index[0]/this.dataScale-1)|0,
40+
this.data.z[0].length-1
41+
),
42+
Math.min(
43+
Math.round(selection.data.index[1]/this.dataScale-1)|0,
44+
this.data.z.length-1
45+
)
46+
];
47+
var traceCoordinate = [0,0,0];
48+
49+
if(Array.isArray(this.data.x[0])) {
50+
traceCoordinate[0] = this.data.x[selectIndex[1]][selectIndex[0]];
51+
} else {
52+
traceCoordinate[0] = this.data.x[selectIndex[0]];
53+
}
54+
if(Array.isArray(this.data.y[0])) {
55+
traceCoordinate[1] = this.data.y[selectIndex[1]][selectIndex[0]];
56+
} else {
57+
traceCoordinate[1] = this.data.y[selectIndex[1]];
58+
}
59+
60+
traceCoordinate[2] = this.data.z[selectIndex[1]][selectIndex[0]];
61+
selection.traceCoordinate = traceCoordinate;
6562

66-
selection.data.dataCoordinate = selection.dataCoordinate.slice();
63+
var sceneLayout = this.scene.fullSceneLayout;
64+
selection.dataCoordinate = [
65+
sceneLayout.xaxis.d2l(traceCoordinate[0]) * this.scene.dataScale[0],
66+
sceneLayout.yaxis.d2l(traceCoordinate[1]) * this.scene.dataScale[1],
67+
sceneLayout.zaxis.d2l(traceCoordinate[2]) * this.scene.dataScale[2]
68+
];
6769

68-
this.surface.highlight(selection.data);
70+
var text = this.data.text;
71+
if(text && text[selectIndex[1]] && text[selectIndex[1]][selectIndex[0]]!==undefined) {
72+
selection.textLabel = text[selectIndex[1]][selectIndex[0]];
73+
}
74+
else selection.textLabel = '';
6975

70-
//Snap spikes to data coordinate
71-
this.scene.glplot.spikes.position = selection.dataCoordinate;
76+
selection.data.dataCoordinate = selection.dataCoordinate.slice();
7277

73-
return true;
74-
}
78+
this.surface.highlight(selection.data);
79+
80+
// Snap spikes to data coordinate
81+
this.scene.glplot.spikes.position = selection.dataCoordinate;
82+
83+
return true;
84+
}
7585
};
7686

7787
function parseColorScale (colorscale, alpha) {
@@ -88,42 +98,44 @@ function parseColorScale (colorscale, alpha) {
8898
});
8999
}
90100

91-
//Pad coords by +1
101+
// Pad coords by +1
92102
function padField(field) {
93-
var shape = field.shape;
94-
var nshape = [shape[0]+2, shape[1]+2];
95-
var nfield = ndarray(new Float32Array(nshape[0] * nshape[1]), nshape);
96-
97-
//Center
98-
ops.assign(nfield.lo(1, 1).hi(shape[0], shape[1]), field);
99-
100-
//Edges
101-
ops.assign(nfield.lo(1).hi(shape[0], 1),
102-
field.hi(shape[0], 1));
103-
ops.assign(nfield.lo(1, nshape[1]-1).hi(shape[0], 1),
104-
field.lo(0, shape[1]-1).hi(shape[0], 1));
105-
ops.assign(nfield.lo(0, 1).hi(1, shape[1]),
106-
field.hi(1));
107-
ops.assign(nfield.lo(nshape[0]-1, 1).hi(1, shape[1]),
108-
field.lo(shape[0]-1));
109-
110-
//Corners
111-
nfield.set(0, 0, field.get(0, 0));
112-
nfield.set(0, nshape[1]-1, field.get(0, shape[1]-1));
113-
nfield.set(nshape[0]-1, 0, field.get(shape[0]-1, 0));
114-
nfield.set(nshape[0]-1, nshape[1]-1, field.get(shape[0]-1, shape[1]-1));
115-
116-
return nfield;
103+
var shape = field.shape;
104+
var nshape = [shape[0]+2, shape[1]+2];
105+
var nfield = ndarray(new Float32Array(nshape[0] * nshape[1]), nshape);
106+
107+
// Center
108+
ops.assign(nfield.lo(1, 1).hi(shape[0], shape[1]), field);
109+
110+
// Edges
111+
ops.assign(nfield.lo(1).hi(shape[0], 1),
112+
field.hi(shape[0], 1));
113+
ops.assign(nfield.lo(1, nshape[1]-1).hi(shape[0], 1),
114+
field.lo(0, shape[1]-1).hi(shape[0], 1));
115+
ops.assign(nfield.lo(0, 1).hi(1, shape[1]),
116+
field.hi(1));
117+
ops.assign(nfield.lo(nshape[0]-1, 1).hi(1, shape[1]),
118+
field.lo(shape[0]-1));
119+
120+
// Corners
121+
nfield.set(0, 0, field.get(0, 0));
122+
nfield.set(0, nshape[1]-1, field.get(0, shape[1]-1));
123+
nfield.set(nshape[0]-1, 0, field.get(shape[0]-1, 0));
124+
nfield.set(nshape[0]-1, nshape[1]-1, field.get(shape[0]-1, shape[1]-1));
125+
126+
return nfield;
117127
}
118128

119129
function refine(coords) {
120130
var minScale = Math.max(coords[0].shape[0], coords[0].shape[1]);
131+
121132
if(minScale < MIN_RESOLUTION) {
122133
var scaleF = MIN_RESOLUTION / minScale;
123134
var nshape = [
124135
Math.floor((coords[0].shape[0]) * scaleF+1)|0,
125136
Math.floor((coords[0].shape[1]) * scaleF+1)|0 ];
126137
var nsize = nshape[0] * nshape[1];
138+
127139
for(var i = 0; i < 3; ++i) {
128140
var padImg = padField(coords[i]);
129141
var scaledImg = ndarray(new Float32Array(nsize), nshape);
@@ -132,20 +144,24 @@ function refine(coords) {
132144
0, 0, 1]);
133145
coords[i] = scaledImg;
134146
}
147+
135148
return scaleF;
136149
}
150+
137151
return 1.0;
138152
}
139153

140154
proto.setContourLevels = function() {
141155
var nlevels = [[], [], []];
142156
var needsUpdate = false;
143-
for(var i=0; i<3; ++i) {
157+
158+
for(var i = 0; i < 3; ++i) {
144159
if(this.showContour[i]) {
145160
needsUpdate = true;
146161
nlevels[i] = this.scene.contourLevels[i];
147162
}
148163
}
164+
149165
if(needsUpdate) {
150166
this.surface.update({ levels: nlevels });
151167
}
@@ -218,20 +234,23 @@ proto.update = function(data) {
218234
this.dataScale = refine(coords);
219235

220236
var params = {
221-
colormap: colormap,
222-
levels: [[], [], []],
223-
showContour: [ true, true, true ],
224-
showSurface: !data.hidesurface,
225-
contourProject: [ [ false, false, false ],
226-
[ false, false, false ],
227-
[ false, false, false ] ],
228-
contourWidth: [ 1, 1, 1 ],
229-
contourColor: [ [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1] ],
230-
contourTint: [ 1, 1, 1 ],
231-
dynamicColor: [ [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1] ],
232-
dynamicWidth: [ 1, 1, 1 ],
233-
dynamicTint: [ 1, 1, 1 ],
234-
opacity: 1
237+
colormap: colormap,
238+
levels: [[], [], []],
239+
showContour: [true, true, true],
240+
showSurface: !data.hidesurface,
241+
contourProject: [
242+
[false, false, false],
243+
[false, false, false],
244+
[false, false, false]
245+
],
246+
contourWidth: [1, 1, 1],
247+
contourColor: [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]],
248+
contourTint: [1, 1, 1],
249+
dynamicColor: [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]],
250+
dynamicWidth: [1, 1, 1],
251+
dynamicTint: [1, 1, 1],
252+
opacity: 1,
253+
colorBounds: [data.zmin * scaleFactor[2], data.zmax * scaleFactor[2]]
235254
};
236255

237256

@@ -241,24 +260,23 @@ proto.update = function(data) {
241260
}
242261
}
243262

244-
var highlightEnable = [ true, true, true ];
245-
var contourEnable = [ true, true, true ];
246-
var axis = [ 'x', 'y', 'z' ];
263+
var highlightEnable = [true, true, true];
264+
var contourEnable = [true, true, true];
265+
var axis = ['x', 'y', 'z'];
247266

248267
for(i = 0; i < 3; ++i) {
249-
var contourParams = data.contours[axis[i]];
250-
highlightEnable[i] = contourParams.highlight;
251-
contourEnable[i] = contourParams.show;
268+
var contourParams = data.contours[axis[i]];
269+
highlightEnable[i] = contourParams.highlight;
270+
contourEnable[i] = contourParams.show;
252271

253-
params.showContour[i] = contourParams.show || contourParams.highlight;
254-
if (!params.showContour[i]) {
255-
continue;
256-
}
272+
params.showContour[i] = contourParams.show || contourParams.highlight;
273+
if(!params.showContour[i]) continue;
257274

258-
params.contourProject[i] = [
275+
params.contourProject[i] = [
259276
contourParams.project.x,
260277
contourParams.project.y,
261-
contourParams.project.z ];
278+
contourParams.project.z
279+
];
262280

263281
if (contourParams.show) {
264282
this.showContour[i] = true;
@@ -283,18 +301,18 @@ proto.update = function(data) {
283301
params.coords = coords;
284302
surface.update(params);
285303

286-
surface.highlightEnable = highlightEnable;
287-
surface.contourEnable = contourEnable;
288-
surface.visible = data.visible;
304+
surface.highlightEnable = highlightEnable;
305+
surface.contourEnable = contourEnable;
306+
surface.visible = data.visible;
289307

290308
surface.snapToData = true;
291309

292310
if ('lighting' in data) {
293-
surface.ambientLight = data.lighting.ambient;
294-
surface.diffuseLight = data.lighting.diffuse;
295-
surface.specularLight = data.lighting.specular;
296-
surface.roughness = data.lighting.roughness;
297-
surface.fresnel = data.lighting.fresnel;
311+
surface.ambientLight = data.lighting.ambient;
312+
surface.diffuseLight = data.lighting.diffuse;
313+
surface.specularLight = data.lighting.specular;
314+
surface.roughness = data.lighting.roughness;
315+
surface.fresnel = data.lighting.fresnel;
298316
}
299317

300318
if (alpha && alpha < 1) {
@@ -304,19 +322,17 @@ proto.update = function(data) {
304322

305323

306324
proto.dispose = function() {
307-
this.glplot.remove(this.surface);
308-
this.surface.dispose();
325+
this.glplot.remove(this.surface);
326+
this.surface.dispose();
309327
};
310328

311329
function createSurfaceTrace(scene, data) {
312-
var gl = scene.glplot.gl;
313-
var surface = createSurface({
314-
gl: gl
315-
});
316-
var result = new SurfaceTrace(scene, surface, data.uid);
317-
result.update(data);
318-
scene.glplot.add(surface);
319-
return result;
330+
var gl = scene.glplot.gl;
331+
var surface = createSurface({ gl: gl });
332+
var result = new SurfaceTrace(scene, surface, data.uid);
333+
result.update(data);
334+
scene.glplot.add(surface);
335+
return result;
320336
}
321337

322338
module.exports = createSurfaceTrace;
-902 Bytes
Loading
155 Bytes
Loading
13 Bytes
Loading
-49 Bytes
Loading
-952 Bytes
Loading
-379 Bytes
Loading
-197 Bytes
Loading
-204 Bytes
Loading

test/image/baselines/gl3d_ribbons.png

385 Bytes
Loading
-180 Bytes
Loading
-61 Bytes
Loading
-217 Bytes
Loading

test/image/mocks/gl3d_autocolorscale.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@
2424
["zero two", "one one", "two one"],
2525
["zero two", "one two", "two two"]
2626
],
27-
"autocolorscale": true
27+
"autocolorscale": true,
28+
"zmin": 0,
29+
"zmax": "50"
2830
}
2931
],
3032
"layout": {

0 commit comments

Comments
 (0)