Skip to content
  • Sponsor plotly/plotly.js

  • Notifications You must be signed in to change notification settings
  • Fork 1.9k
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bar3d new trace type #7003

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
isosurface > bar3d
archmoj committed May 22, 2024
commit 92c0379f6204cd03b5c4bb58020be5096ba86fe8
236 changes: 236 additions & 0 deletions src/traces/bar3d/attributes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
'use strict';

var colorScaleAttrs = require('../../components/colorscale/attributes');
var axisHoverFormat = require('../../plots/cartesian/axis_format_attributes').axisHoverFormat;
var hovertemplateAttrs = require('../../plots/template_attributes').hovertemplateAttrs;
var meshAttrs = require('../mesh3d/attributes');
var baseAttrs = require('../../plots/attributes');

var extendFlat = require('../../lib/extend').extendFlat;
var overrideAll = require('../../plot_api/edit_types').overrideAll;

function makeSliceAttr(axLetter) {
return {
show: {
valType: 'boolean',
dflt: false,
description: [
'Determines whether or not slice planes about the', axLetter,
'dimension are drawn.'
].join(' ')
},
locations: {
valType: 'data_array',
dflt: [],
description: [
'Specifies the location(s) of slices on the axis.',
'When not specified slices would be created for',
'all points of the axis', axLetter, 'except start and end.'
].join(' ')
},
fill: {
valType: 'number',
min: 0,
max: 1,
dflt: 1,
description: [
'Sets the fill ratio of the `slices`. The default fill value of the',
'`slices` is 1 meaning that they are entirely shaded. On the other hand',
'Applying a `fill` ratio less than one would allow the creation of',
'openings parallel to the edges.'
].join(' ')
}
};
}

function makeCapAttr(axLetter) {
return {
show: {
valType: 'boolean',
dflt: true,
description: [
'Sets the fill ratio of the `slices`. The default fill value of the', axLetter,
'`slices` is 1 meaning that they are entirely shaded. On the other hand',
'Applying a `fill` ratio less than one would allow the creation of',
'openings parallel to the edges.'
].join(' ')
},
fill: {
valType: 'number',
min: 0,
max: 1,
dflt: 1,
description: [
'Sets the fill ratio of the `caps`. The default fill value of the',
'`caps` is 1 meaning that they are entirely shaded. On the other hand',
'Applying a `fill` ratio less than one would allow the creation of',
'openings parallel to the edges.'
].join(' ')
}
};
}

var attrs = module.exports = overrideAll(extendFlat({
x: {
valType: 'data_array',
description: [
'Sets the X coordinates of the vertices on X axis.'
].join(' ')
},
y: {
valType: 'data_array',
description: [
'Sets the Y coordinates of the vertices on Y axis.'
].join(' ')
},
z: {
valType: 'data_array',
description: [
'Sets the Z coordinates of the vertices on Z axis.'
].join(' ')
},
value: {
valType: 'data_array',
description: [
'Sets the 4th dimension (value) of the vertices.'
].join(' ')
},
isomin: {
valType: 'number',
description: [
'Sets the minimum boundary for iso-surface plot.'
].join(' ')
},
isomax: {
valType: 'number',
description: [
'Sets the maximum boundary for iso-surface plot.'
].join(' ')
},

surface: {
show: {
valType: 'boolean',
dflt: true,
description: [
'Hides/displays surfaces between minimum and maximum iso-values.'
].join(' ')
},
count: {
valType: 'integer',
dflt: 2,
min: 1,
description: [
'Sets the number of iso-surfaces between minimum and maximum iso-values.',
'By default this value is 2 meaning that only minimum and maximum surfaces',
'would be drawn.'
].join(' ')
},
fill: {
valType: 'number',
min: 0,
max: 1,
dflt: 1,
description: [
'Sets the fill ratio of the iso-surface. The default fill value of the',
'surface is 1 meaning that they are entirely shaded. On the other hand',
'Applying a `fill` ratio less than one would allow the creation of',
'openings parallel to the edges.'
].join(' ')
},
pattern: {
valType: 'flaglist',
flags: ['A', 'B', 'C', 'D', 'E'],
extras: ['all', 'odd', 'even'],
dflt: 'all',
description: [
'Sets the surface pattern of the iso-surface 3-D sections. The default pattern of',
'the surface is `all` meaning that the rest of surface elements would be shaded.',
'The check options (either 1 or 2) could be used to draw half of the squares',
'on the surface. Using various combinations of capital `A`, `B`, `C`, `D` and `E`',
'may also be used to reduce the number of triangles on the iso-surfaces and',
'creating other patterns of interest.'
].join(' ')
}
},

spaceframe: {
show: {
valType: 'boolean',
dflt: false,
description: [
'Displays/hides tetrahedron shapes between minimum and',
'maximum iso-values. Often useful when either caps or',
'surfaces are disabled or filled with values less than 1.'
].join(' ')
},
fill: {
valType: 'number',
min: 0,
max: 1,
dflt: 0.15,
description: [
'Sets the fill ratio of the `spaceframe` elements. The default fill value',
'is 0.15 meaning that only 15% of the area of every faces of tetras would be',
'shaded. Applying a greater `fill` ratio would allow the creation of stronger',
'elements or could be sued to have entirely closed areas (in case of using 1).'
].join(' ')
}
},

slices: {
x: makeSliceAttr('x'),
y: makeSliceAttr('y'),
z: makeSliceAttr('z')
},

caps: {
x: makeCapAttr('x'),
y: makeCapAttr('y'),
z: makeCapAttr('z')
},

text: {
valType: 'string',
dflt: '',
arrayOk: true,
description: [
'Sets the text elements associated with the vertices.',
'If trace `hoverinfo` contains a *text* flag and *hovertext* is not set,',
'these elements will be seen in the hover labels.'
].join(' ')
},
hovertext: {
valType: 'string',
dflt: '',
arrayOk: true,
description: 'Same as `text`.'
},
hovertemplate: hovertemplateAttrs(),
xhoverformat: axisHoverFormat('x'),
yhoverformat: axisHoverFormat('y'),
zhoverformat: axisHoverFormat('z'),
valuehoverformat: axisHoverFormat('value', 1),

showlegend: extendFlat({}, baseAttrs.showlegend, {dflt: false})
},

colorScaleAttrs('', {
colorAttr: '`value`',
showScaleDflt: true,
editTypeOverride: 'calc'
}), {
opacity: meshAttrs.opacity,
lightposition: meshAttrs.lightposition,
lighting: meshAttrs.lighting,
flatshading: meshAttrs.flatshading,
contour: meshAttrs.contour,

hoverinfo: extendFlat({}, baseAttrs.hoverinfo)
}), 'calc', 'nested');

// required defaults to speed up surface normal calculations
attrs.flatshading.dflt = true; attrs.lighting.facenormalsepsilon.dflt = 0;

attrs.x.editType = attrs.y.editType = attrs.z.editType = attrs.value.editType = 'calc+clearAxisTypes';
attrs.transforms = undefined;
45 changes: 45 additions & 0 deletions src/traces/bar3d/calc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
'use strict';

var colorscaleCalc = require('../../components/colorscale/calc');
var processGrid = require('../streamtube/calc').processGrid;
var filter = require('../streamtube/calc').filter;

module.exports = function calc(gd, trace) {
trace._len = Math.min(
trace.x.length,
trace.y.length,
trace.z.length,
trace.value.length
);

trace._x = filter(trace.x, trace._len);
trace._y = filter(trace.y, trace._len);
trace._z = filter(trace.z, trace._len);
trace._value = filter(trace.value, trace._len);

var grid = processGrid(trace);
trace._gridFill = grid.fill;
trace._Xs = grid.Xs;
trace._Ys = grid.Ys;
trace._Zs = grid.Zs;
trace._len = grid.len;

var min = Infinity;
var max = -Infinity;
for(var i = 0; i < trace._len; i++) {
var v = trace._value[i];
min = Math.min(min, v);
max = Math.max(max, v);
}

trace._minValues = min;
trace._maxValues = max;
trace._vMin = (trace.isomin === undefined || trace.isomin === null) ? min : trace.isomin;
trace._vMax = (trace.isomax === undefined || trace.isomin === null) ? max : trace.isomax;

colorscaleCalc(gd, trace, {
vals: [trace._vMin, trace._vMax],
containerStr: '',
cLetter: 'c'
});
};
1,047 changes: 1,047 additions & 0 deletions src/traces/bar3d/convert.js

Large diffs are not rendered by default.

110 changes: 110 additions & 0 deletions src/traces/bar3d/defaults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
'use strict';

var Lib = require('../../lib');
var Registry = require('../../registry');
var attributes = require('./attributes');
var colorscaleDefaults = require('../../components/colorscale/defaults');

function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
function coerce(attr, dflt) {
return Lib.coerce(traceIn, traceOut, attributes, attr, dflt);
}

supplyIsoDefaults(traceIn, traceOut, defaultColor, layout, coerce);
}

function supplyIsoDefaults(traceIn, traceOut, defaultColor, layout, coerce) {
var isomin = coerce('isomin');
var isomax = coerce('isomax');

if(isomax !== undefined && isomax !== null &&
isomin !== undefined && isomin !== null &&
isomin > isomax) {
// applying default values in this case:
traceOut.isomin = null;
traceOut.isomax = null;
}

var x = coerce('x');
var y = coerce('y');
var z = coerce('z');
var value = coerce('value');

if(
!x || !x.length ||
!y || !y.length ||
!z || !z.length ||
!value || !value.length
) {
traceOut.visible = false;
return;
}

var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults');
handleCalendarDefaults(traceIn, traceOut, ['x', 'y', 'z'], layout);

coerce('valuehoverformat');
['x', 'y', 'z'].forEach(function(dim) {
coerce(dim + 'hoverformat');

var capDim = 'caps.' + dim;
var showCap = coerce(capDim + '.show');
if(showCap) {
coerce(capDim + '.fill');
}

var sliceDim = 'slices.' + dim;
var showSlice = coerce(sliceDim + '.show');
if(showSlice) {
coerce(sliceDim + '.fill');
coerce(sliceDim + '.locations');
}
});

var showSpaceframe = coerce('spaceframe.show');
if(showSpaceframe) {
coerce('spaceframe.fill');
}

var showSurface = coerce('surface.show');
if(showSurface) {
coerce('surface.count');
coerce('surface.fill');
coerce('surface.pattern');
}

var showContour = coerce('contour.show');
if(showContour) {
coerce('contour.color');
coerce('contour.width');
}

// Coerce remaining properties
[
'text',
'hovertext',
'hovertemplate',
'lighting.ambient',
'lighting.diffuse',
'lighting.specular',
'lighting.roughness',
'lighting.fresnel',
'lighting.vertexnormalsepsilon',
'lighting.facenormalsepsilon',
'lightposition.x',
'lightposition.y',
'lightposition.z',
'flatshading',
'opacity'
].forEach(function(x) { coerce(x); });

colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'c'});

// disable 1D transforms (for now)
traceOut._length = null;
}

module.exports = {
supplyDefaults: supplyDefaults,
supplyIsoDefaults: supplyIsoDefaults
};
25 changes: 25 additions & 0 deletions src/traces/bar3d/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
'use strict';

module.exports = {
attributes: require('./attributes'),
supplyDefaults: require('./defaults').supplyDefaults,
calc: require('./calc'),
colorbar: {
min: 'cmin',
max: 'cmax'
},
plot: require('./convert').createbar3dTrace,

moduleType: 'trace',
name: 'bar3d',
basePlotModule: require('../../plots/gl3d'),
categories: ['gl3d', 'showLegend'],
meta: {
description: [
'Draws bar3ds between iso-min and iso-max values with coordinates given by',
'four 1-dimensional arrays containing the `value`, `x`, `y` and `z` of every vertex',
'of a uniform or non-uniform 3-D grid. Horizontal or vertical slices, caps as well as',
'spaceframe between iso-min and iso-max values could also be drawn using this trace.'
].join(' ')
}
};