diff --git a/package.json b/package.json index aa7e294160e..e4df8b7987a 100644 --- a/package.json +++ b/package.json @@ -66,12 +66,12 @@ "fast-isnumeric": "^1.1.1", "gl-contour2d": "^1.1.2", "gl-error2d": "^1.2.1", - "gl-error3d": "^1.0.5", + "gl-error3d": "^1.0.6", "gl-heatmap2d": "^1.0.3", "gl-line2d": "^1.4.1", "gl-line3d": "^1.1.0", "gl-mat4": "^1.1.2", - "gl-mesh3d": "^1.2.0", + "gl-mesh3d": "^1.3.0", "gl-plot2d": "^1.2.0", "gl-plot3d": "^1.5.4", "gl-pointcloud2d": "^1.0.0", diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index cf0c268d955..1643b821025 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -1383,6 +1383,7 @@ function _restyle(gd, aobj, _traces) { ]; var zscl = ['zmin', 'zmax'], + cscl = ['cmin', 'cmax'], xbins = ['xbins.start', 'xbins.end', 'xbins.size'], ybins = ['ybins.start', 'ybins.end', 'ybins.size'], contourAttrs = ['contours.start', 'contours.end', 'contours.size']; @@ -1482,6 +1483,9 @@ function _restyle(gd, aobj, _traces) { if(zscl.indexOf(ai) !== -1) { doextra('zauto', false, i); } + if(cscl.indexOf(ai) !== -1) { + doextra('cauto', false, i); + } else if(ai === 'colorscale') { doextra('autocolorscale', false, i); } diff --git a/src/traces/mesh3d/attributes.js b/src/traces/mesh3d/attributes.js index cfc573724fc..a21d81956d5 100644 --- a/src/traces/mesh3d/attributes.js +++ b/src/traces/mesh3d/attributes.js @@ -165,8 +165,12 @@ module.exports = { width: extendFlat({}, surfaceAtts.contours.x.width) }, + cauto: colorscaleAttrs.zauto, + cmin: colorscaleAttrs.zmin, + cmax: colorscaleAttrs.zmax, colorscale: colorscaleAttrs.colorscale, reversescale: colorscaleAttrs.reversescale, + autocolorscale: extendFlat({}, colorscaleAttrs.autocolorscale, {dflt: false}), showscale: colorscaleAttrs.showscale, colorbar: colorbarAttrs, diff --git a/src/traces/mesh3d/calc.js b/src/traces/mesh3d/calc.js new file mode 100644 index 00000000000..a0171270f37 --- /dev/null +++ b/src/traces/mesh3d/calc.js @@ -0,0 +1,17 @@ +/** +* Copyright 2012-2017, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorscaleCalc = require('../../components/colorscale/calc'); + +module.exports = function calc(gd, trace) { + if(trace.intensity) { + colorscaleCalc(trace, trace.intensity, '', 'c'); + } +}; diff --git a/src/traces/mesh3d/colorbar.js b/src/traces/mesh3d/colorbar.js new file mode 100644 index 00000000000..5cc4b5bcd8d --- /dev/null +++ b/src/traces/mesh3d/colorbar.js @@ -0,0 +1,48 @@ +/** +* Copyright 2012-2017, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var isNumeric = require('fast-isnumeric'); + +var Lib = require('../../lib'); +var Plots = require('../../plots/plots'); +var Colorscale = require('../../components/colorscale'); +var drawColorbar = require('../../components/colorbar/draw'); + +module.exports = function colorbar(gd, cd) { + var trace = cd[0].trace, + cbId = 'cb' + trace.uid, + cmin = trace.cmin, + cmax = trace.cmax, + vals = trace.intensity || []; + + if(!isNumeric(cmin)) cmin = Lib.aggNums(Math.min, null, vals); + if(!isNumeric(cmax)) cmax = Lib.aggNums(Math.max, null, vals); + + gd._fullLayout._infolayer.selectAll('.' + cbId).remove(); + + if(!trace.showscale) { + Plots.autoMargin(gd, cbId); + return; + } + + var cb = cd[0].t.cb = drawColorbar(gd, cbId); + var sclFunc = Colorscale.makeColorScaleFunc( + Colorscale.extractScale( + trace.colorscale, + cmin, + cmax + ), + { noNumericCheck: true } + ); + + cb.fillcolor(sclFunc) + .filllevels({start: cmin, end: cmax, size: (cmax - cmin) / 254}) + .options(trace.colorbar)(); +}; diff --git a/src/traces/mesh3d/convert.js b/src/traces/mesh3d/convert.js index bf675bb7f8e..28e45325a40 100644 --- a/src/traces/mesh3d/convert.js +++ b/src/traces/mesh3d/convert.js @@ -124,6 +124,7 @@ proto.update = function(data) { if(data.intensity) { this.color = '#fff'; config.vertexIntensity = data.intensity; + config.vertexIntensityBounds = [data.cmin, data.cmax]; config.colormap = parseColorScale(data.colorscale); } else if(data.vertexcolor) { diff --git a/src/traces/mesh3d/defaults.js b/src/traces/mesh3d/defaults.js index 87ff1aabf1c..c5382400fce 100644 --- a/src/traces/mesh3d/defaults.js +++ b/src/traces/mesh3d/defaults.js @@ -11,10 +11,9 @@ var Registry = require('../../registry'); var Lib = require('../../lib'); -var colorbarDefaults = require('../../components/colorbar/defaults'); +var colorscaleDefaults = require('../../components/colorscale/defaults'); var attributes = require('./attributes'); - module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { function coerce(attr, dflt) { return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); @@ -77,23 +76,12 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout if('intensity' in traceIn) { coerce('intensity'); - coerce('showscale', true); - } - else { + colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'c'}); + } else { traceOut.showscale = false; if('facecolor' in traceIn) coerce('facecolor'); else if('vertexcolor' in traceIn) coerce('vertexcolor'); else coerce('color', defaultColor); } - - if(traceOut.reversescale) { - traceOut.colorscale = traceOut.colorscale.map(function(si) { - return [1 - si[0], si[1]]; - }).reverse(); - } - - if(traceOut.showscale) { - colorbarDefaults(traceIn, traceOut, layout); - } }; diff --git a/src/traces/mesh3d/index.js b/src/traces/mesh3d/index.js index 34eed6c6aa9..8506fb81814 100644 --- a/src/traces/mesh3d/index.js +++ b/src/traces/mesh3d/index.js @@ -13,7 +13,8 @@ var Mesh3D = {}; Mesh3D.attributes = require('./attributes'); Mesh3D.supplyDefaults = require('./defaults'); -Mesh3D.colorbar = require('../heatmap/colorbar'); +Mesh3D.calc = require('./calc'); +Mesh3D.colorbar = require('./colorbar'); Mesh3D.plot = require('./convert'); Mesh3D.moduleType = 'trace'; diff --git a/src/traces/surface/attributes.js b/src/traces/surface/attributes.js index 6e3930a0479..35761fd4496 100644 --- a/src/traces/surface/attributes.js +++ b/src/traces/surface/attributes.js @@ -122,7 +122,6 @@ module.exports = { ].join(' ') }, - // Todo this block has a structure of colorscale/attributes.js but with colorscale/color_attributes.js names cauto: colorscaleAttrs.zauto, cmin: colorscaleAttrs.zmin, cmax: colorscaleAttrs.zmax, diff --git a/test/image/baselines/gl3d_bunny-hull.png b/test/image/baselines/gl3d_bunny-hull.png index 9a036a39905..ce9978455d9 100644 Binary files a/test/image/baselines/gl3d_bunny-hull.png and b/test/image/baselines/gl3d_bunny-hull.png differ diff --git a/test/image/baselines/gl3d_bunny.png b/test/image/baselines/gl3d_bunny.png index f71b606da6f..4cb5a8ccafc 100644 Binary files a/test/image/baselines/gl3d_bunny.png and b/test/image/baselines/gl3d_bunny.png differ diff --git a/test/image/baselines/gl3d_convex-hull.png b/test/image/baselines/gl3d_convex-hull.png index f71b606da6f..4cb5a8ccafc 100644 Binary files a/test/image/baselines/gl3d_convex-hull.png and b/test/image/baselines/gl3d_convex-hull.png differ diff --git a/test/image/baselines/gl3d_tetrahedra.png b/test/image/baselines/gl3d_tetrahedra.png index f64a8318027..ddd599e69c4 100644 Binary files a/test/image/baselines/gl3d_tetrahedra.png and b/test/image/baselines/gl3d_tetrahedra.png differ diff --git a/test/image/mocks/gl3d_tetrahedra.json b/test/image/mocks/gl3d_tetrahedra.json index 62d45514e19..240ac64e820 100644 --- a/test/image/mocks/gl3d_tetrahedra.json +++ b/test/image/mocks/gl3d_tetrahedra.json @@ -16,6 +16,8 @@ [1, "rgb(0, 0, 255)"] ], "intensity": [0, 0.33, 0.66, 1], + "cmin": -0.5, + "cmax": 0.5, "colorbar": { "x": 0, "title": "for colorscale + intensity tetrahedra", diff --git a/test/jasmine/tests/mesh3d_test.js b/test/jasmine/tests/mesh3d_test.js new file mode 100644 index 00000000000..982c7913765 --- /dev/null +++ b/test/jasmine/tests/mesh3d_test.js @@ -0,0 +1,57 @@ +var Plotly = require('@lib'); +var createGraphDiv = require('../assets/create_graph_div'); +var destroyGraphDiv = require('../assets/destroy_graph_div'); +var fail = require('../assets/fail_test'); + +describe('Test mesh3d restyle', function() { + afterEach(destroyGraphDiv); + + it('should clear *cauto* when restyle *cmin* and/or *cmax*', function(done) { + var gd = createGraphDiv(); + + function _assert(user, full) { + var trace = gd.data[0]; + var fullTrace = gd._fullData[0]; + + expect(trace.cauto).toBe(user[0], 'user cauto'); + expect(trace.cmin).toEqual(user[1], 'user cmin'); + expect(trace.cmax).toEqual(user[2], 'user cmax'); + expect(fullTrace.cauto).toBe(full[0], 'full cauto'); + expect(fullTrace.cmin).toEqual(full[1], 'full cmin'); + expect(fullTrace.cmax).toEqual(full[2], 'full cmax'); + } + + Plotly.plot(gd, [{ + type: 'mesh3d', + x: [0, 1, 2, 0], + y: [0, 0, 1, 2], + z: [0, 2, 0, 1], + i: [0, 0, 0, 1], + j: [1, 2, 3, 2], + k: [2, 3, 1, 3], + intensity: [0, 0.33, 0.66, 3] + }]) + .then(function() { + _assert([true, 0, 3], [true, 0, 3]); + + return Plotly.restyle(gd, 'cmin', 0); + }) + .then(function() { + _assert([false, 0, 3], [false, 0, 3]); + + return Plotly.restyle(gd, 'cmax', 10); + }) + .then(function() { + _assert([false, 0, 10], [false, 0, 10]); + + return Plotly.restyle(gd, 'cauto', true); + }) + .then(function() { + _assert([true, 0, 3], [true, 0, 3]); + + return Plotly.purge(gd); + }) + .catch(fail) + .then(done); + }); +});