Skip to content

Commit ed3deda

Browse files
committed
Merge pull request #347 from plotly/fix-surface-intensity
Add `surfacecolor` functionality to surface traces
2 parents e891bac + 15354d2 commit ed3deda

File tree

15 files changed

+537
-17
lines changed

15 files changed

+537
-17
lines changed

devtools/test_dashboard/test_gl3d.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ plots['marker-arrays'] = require('@mocks/gl3d_marker-arrays.json');
3535
plots['scatter3d-colorscale'] = require('@mocks/gl3d_scatter3d-colorscale.json');
3636
plots['autocolorscale'] = require('@mocks/gl3d_autocolorscale.json');
3737
plots['nan-holes'] = require('@mocks/gl3d_nan-holes.json');
38-
plots['tetrahedra'] = require('@mocks/gl3d_tet.json');
38+
plots['tet'] = require('@mocks/gl3d_tet.json');
39+
plots['surface_intensity'] = require('@mocks/gl3d_surface_intensity.json');
3940

4041
plotButtons(plots, figDir);

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
"gl-scatter3d": "^1.0.4",
6565
"gl-select-box": "^1.0.1",
6666
"gl-spikes2d": "^1.0.1",
67-
"gl-surface3d": "^1.1.1",
67+
"gl-surface3d": "^1.2.3",
6868
"mouse-change": "^1.1.1",
6969
"mouse-wheel": "^1.0.2",
7070
"ndarray": "^1.0.16",

src/traces/choropleth/calc.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* Copyright 2012-2016, Plotly, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
10+
'use strict';
11+
12+
var colorscaleCalc = require('../../components/colorscale/calc');
13+
14+
15+
module.exports = function calc(gd, trace) {
16+
colorscaleCalc(trace, trace.z, '', 'z');
17+
};

src/traces/choropleth/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ var Choropleth = {};
1414
Choropleth.attributes = require('./attributes');
1515
Choropleth.supplyDefaults = require('./defaults');
1616
Choropleth.colorbar = require('../heatmap/colorbar');
17-
Choropleth.calc = require('../surface/calc');
17+
Choropleth.calc = require('./calc');
1818
Choropleth.plot = require('./plot').plot;
1919

2020
Choropleth.moduleType = 'trace';

src/traces/surface/attributes.js

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,16 @@ module.exports = {
9595
valType: 'data_array',
9696
description: 'Sets the text elements associated with each z value.'
9797
},
98-
zauto: colorscaleAttrs.zauto,
99-
zmin: colorscaleAttrs.zmin,
100-
zmax: colorscaleAttrs.zmax,
98+
surfacecolor: {
99+
valType: 'data_array',
100+
description: [
101+
'Sets the surface color values,',
102+
'used for setting a color scale independent of `z`.'
103+
].join(' ')
104+
},
105+
cauto: colorscaleAttrs.zauto,
106+
cmin: colorscaleAttrs.zmin,
107+
cmax: colorscaleAttrs.zmax,
101108
colorscale: colorscaleAttrs.colorscale,
102109
autocolorscale: extendFlat({}, colorscaleAttrs.autocolorscale,
103110
{dflt: false}),
@@ -161,5 +168,17 @@ module.exports = {
161168

162169
_nestedModules: { // nested module coupling
163170
'colorbar': 'Colorbar'
171+
},
172+
173+
_deprecated: {
174+
zauto: extendFlat({}, colorscaleAttrs.zauto, {
175+
description: 'Obsolete. Use `cauto` instead.'
176+
}),
177+
zmin: extendFlat({}, colorscaleAttrs.zmin, {
178+
description: 'Obsolete. Use `cmin` instead.'
179+
}),
180+
zmax: extendFlat({}, colorscaleAttrs.zmax, {
181+
description: 'Obsolete. Use `cmax` instead.'
182+
})
164183
}
165184
};

src/traces/surface/calc.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,9 @@ var colorscaleCalc = require('../../components/colorscale/calc');
1414

1515
// Compute auto-z and autocolorscale if applicable
1616
module.exports = function calc(gd, trace) {
17-
colorscaleCalc(trace, trace.z, '', 'z');
17+
if(trace.surfacecolor) {
18+
colorscaleCalc(trace, trace.surfacecolor, '', 'c');
19+
} else {
20+
colorscaleCalc(trace, trace.z, '', 'c');
21+
}
1822
};

src/traces/surface/colorbar.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* Copyright 2012-2016, Plotly, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
10+
'use strict';
11+
12+
var d3 = require('d3');
13+
var isNumeric = require('fast-isnumeric');
14+
15+
var Lib = require('../../lib');
16+
var Plots = require('../../plots/plots');
17+
var getColorscale = require('../../components/colorscale/get_scale');
18+
var drawColorbar = require('../../components/colorbar/draw');
19+
20+
21+
module.exports = function colorbar(gd, cd) {
22+
var trace = cd[0].trace,
23+
cbId = 'cb' + trace.uid,
24+
scl = getColorscale(trace.colorscale),
25+
zmin = trace.cmin,
26+
zmax = trace.cmax,
27+
vals = trace.surfacecolor || trace.z;
28+
29+
if(!isNumeric(zmin)) zmin = Lib.aggNums(Math.min, null, vals);
30+
if(!isNumeric(zmax)) zmax = Lib.aggNums(Math.max, null, vals);
31+
32+
gd._fullLayout._infolayer.selectAll('.' + cbId).remove();
33+
34+
if(!trace.showscale) {
35+
Plots.autoMargin(gd, cbId);
36+
return;
37+
}
38+
39+
var cb = cd[0].t.cb = drawColorbar(gd, cbId);
40+
cb.fillcolor(d3.scale.linear()
41+
.domain(scl.map(function(v) { return zmin + v[0]*(zmax-zmin); }))
42+
.range(scl.map(function(v) { return v[1]; })))
43+
.filllevels({start: zmin, end: zmax, size: (zmax-zmin)/254})
44+
.options(trace.colorbar)();
45+
46+
Lib.markTime('done colorbar');
47+
};

src/traces/surface/convert.js

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ var str2RgbaArray = require('../../lib/str2rgbarray');
2020

2121
var MIN_RESOLUTION = 128;
2222

23-
2423
function SurfaceTrace(scene, surface, uid) {
2524
this.scene = scene;
2625
this.uid = uid;
@@ -136,7 +135,7 @@ function refine(coords) {
136135
Math.floor((coords[0].shape[1]) * scaleF+1)|0 ];
137136
var nsize = nshape[0] * nshape[1];
138137

139-
for(var i = 0; i < 3; ++i) {
138+
for(var i = 0; i < coords.length; ++i) {
140139
var padImg = padField(coords[i]);
141140
var scaledImg = ndarray(new Float32Array(nsize), nshape);
142141
homography(scaledImg, padImg, [scaleF, 0, 0,
@@ -230,9 +229,6 @@ proto.update = function(data) {
230229
});
231230
}
232231

233-
//Refine if necessary
234-
this.dataScale = refine(coords);
235-
236232
var params = {
237233
colormap: colormap,
238234
levels: [[], [], []],
@@ -249,10 +245,33 @@ proto.update = function(data) {
249245
dynamicColor: [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]],
250246
dynamicWidth: [1, 1, 1],
251247
dynamicTint: [1, 1, 1],
252-
opacity: 1,
253-
colorBounds: [data.zmin * scaleFactor[2], data.zmax * scaleFactor[2]]
248+
opacity: 1
254249
};
255250

251+
params.intensityBounds = [data.cmin, data.cmax];
252+
253+
//Refine if necessary
254+
if(data.surfacecolor) {
255+
var intensity = ndarray(new Float32Array(xlen * ylen), [xlen, ylen]);
256+
257+
fill(intensity, function(row, col) {
258+
return data.surfacecolor[col][row];
259+
});
260+
261+
coords.push(intensity);
262+
}
263+
else {
264+
// when 'z' is used as 'intensity',
265+
// we must scale its value
266+
params.intensityBounds[0] *= scaleFactor[2];
267+
params.intensityBounds[1] *= scaleFactor[2];
268+
}
269+
270+
this.dataScale = refine(coords);
271+
272+
if(data.surfacecolor) {
273+
params.intensity = coords.pop();
274+
}
256275

257276
if('opacity' in data) {
258277
if(data.opacity < 1) {
@@ -300,6 +319,7 @@ proto.update = function(data) {
300319
}
301320

302321
params.coords = coords;
322+
303323
surface.update(params);
304324

305325
surface.highlightEnable = highlightEnable;

src/traces/surface/defaults.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
5858
coerce('hidesurface');
5959
coerce('opacity');
6060

61+
var surfaceColor = coerce('surfacecolor');
62+
6163
coerce('colorscale');
6264

6365
var dims = ['x', 'y', 'z'];
@@ -85,7 +87,20 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
8587
}
8688
}
8789

90+
// backward compatibility block
91+
if(!surfaceColor) {
92+
mapLegacy(traceIn, 'zmin', 'cmin');
93+
mapLegacy(traceIn, 'zmax', 'cmax');
94+
mapLegacy(traceIn, 'zauto', 'cauto');
95+
}
96+
8897
colorscaleDefaults(
89-
traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'z'}
98+
traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'c'}
9099
);
91100
};
101+
102+
function mapLegacy(traceIn, oldAttr, newAttr) {
103+
if(oldAttr in traceIn && !(newAttr in traceIn)) {
104+
traceIn[newAttr] = traceIn[oldAttr];
105+
}
106+
}

src/traces/surface/index.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ var Surface = {};
1313

1414
Surface.attributes = require('./attributes');
1515
Surface.supplyDefaults = require('./defaults');
16-
Surface.colorbar = require('../heatmap/colorbar');
16+
Surface.colorbar = require('./colorbar');
1717
Surface.calc = require('./calc');
1818
Surface.plot = require('./convert');
1919

@@ -30,7 +30,11 @@ Surface.meta = {
3030
'or {2D arrays} (e.g. to graph parametric surfaces).',
3131

3232
'If not provided in `x` and `y`, the x and y coordinates are assumed',
33-
'to be linear starting at 0 with a unit step.'
33+
'to be linear starting at 0 with a unit step.',
34+
35+
'The color scale corresponds to the `z` values by default.',
36+
'For custom color scales, use `surfacecolor` which should be a {2D array},',
37+
'where its bounds can be controlled using `cmin` and `cmax`.'
3438
].join(' ')
3539
};
3640

-144 Bytes
Loading
-220 Bytes
Loading
Loading

0 commit comments

Comments
 (0)