'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 mesh3dAttrs = require('../mesh3d/attributes'); var baseAttrs = require('../../plots/attributes'); var extendFlat = require('../../lib/extend').extendFlat; var attrs = { x: { valType: 'data_array', editType: 'calc+clearAxisTypes', description: [ 'Sets the x coordinates of the vector field', 'and of the displayed cones.' ].join(' ') }, y: { valType: 'data_array', editType: 'calc+clearAxisTypes', description: [ 'Sets the y coordinates of the vector field', 'and of the displayed cones.' ].join(' ') }, z: { valType: 'data_array', editType: 'calc+clearAxisTypes', description: [ 'Sets the z coordinates of the vector field', 'and of the displayed cones.' ].join(' ') }, u: { valType: 'data_array', editType: 'calc', description: 'Sets the x components of the vector field.' }, v: { valType: 'data_array', editType: 'calc', description: 'Sets the y components of the vector field.' }, w: { valType: 'data_array', editType: 'calc', description: 'Sets the z components of the vector field.' }, // TODO add way to specify cone positions independently of the vector field // provided, similar to MATLAB's coneplot Cx/Cy/Cz meshgrids, // see https://www.mathworks.com/help/matlab/ref/coneplot.html // // Alternatively, if our goal is only to 'fill in gaps' in the vector data, // we could try to extend the heatmap 'connectgaps' algorithm to 3D. // From AJ: this particular algorithm which amounts to a Poisson equation, // both for interpolation and extrapolation - is the right one to use for // cones too. It makes a field with zero divergence, which is a good // baseline assumption for vector fields. // // cones: { // // potential attributes to add: // // // // - meshmode: 'cartesian-product', 'pts', 'grid' // // // // under `meshmode: 'grid'` // // - (x|y|z)grid.start // // - (x|y|z)grid.end // // - (x|y|z)grid.size // // x: { // valType: 'data_array', // editType: 'calc', // description: 'Sets the x coordinates of the cones to be displayed.' // }, // y: { // valType: 'data_array', // editType: 'calc', // description: 'Sets the y coordinates of the cones to be displayed.' // }, // z: { // valType: 'data_array', // editType: 'calc', // description: 'Sets the z coordinates of the cones to be displayed.' // }, // // editType: 'calc', // description: [ // 'By setting `cones.x`, `cones.y` and `cones.z` to 1D arrays,', // 'plotly creates a mesh using the cartesian product of those 3 arrays.' // ].join(' ') // }, sizemode: { valType: 'enumerated', values: ['scaled', 'absolute', 'raw'], editType: 'calc', dflt: 'scaled', description: [ 'Determines whether `sizeref` is set as a *scaled* (i.e unitless) scalar', '(normalized by the max u/v/w norm in the vector field) or as', '*absolute* value (in the same units as the vector field).', 'To display sizes in actual vector length use *raw*.' ].join(' ') }, sizeref: { valType: 'number', editType: 'calc', min: 0, description: [ 'Adjusts the cone size scaling.', 'The size of the cones is determined by their u/v/w norm multiplied a factor and `sizeref`.', 'This factor (computed internally) corresponds to the minimum "time" to travel across', 'two successive x/y/z positions at the average velocity of those two successive positions.', 'All cones in a given trace use the same factor.', 'With `sizemode` set to *raw*, its default value is *1*.', 'With `sizemode` set to *scaled*, `sizeref` is unitless, its default value is *0.5*.', 'With `sizemode` set to *absolute*, `sizeref` has the same units as the u/v/w vector field,', 'its the default value is half the sample\'s maximum vector norm.' ].join(' ') }, anchor: { valType: 'enumerated', editType: 'calc', values: ['tip', 'tail', 'cm', 'center'], dflt: 'cm', description: [ 'Sets the cones\' anchor with respect to their x/y/z positions.', 'Note that *cm* denote the cone\'s center of mass which corresponds to', '1/4 from the tail to tip.' ].join(' ') }, text: { valType: 'string', dflt: '', arrayOk: true, editType: 'calc', description: [ 'Sets the text elements associated with the cones.', '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, editType: 'calc', description: 'Same as `text`.' }, hovertemplate: hovertemplateAttrs({editType: 'calc'}, {keys: ['norm']}), uhoverformat: axisHoverFormat('u', 1), vhoverformat: axisHoverFormat('v', 1), whoverformat: axisHoverFormat('w', 1), xhoverformat: axisHoverFormat('x'), yhoverformat: axisHoverFormat('y'), zhoverformat: axisHoverFormat('z'), showlegend: extendFlat({}, baseAttrs.showlegend, {dflt: false}) }; extendFlat(attrs, colorScaleAttrs('', { colorAttr: 'u/v/w norm', showScaleDflt: true, editTypeOverride: 'calc' })); var fromMesh3d = ['opacity', 'lightposition', 'lighting']; fromMesh3d.forEach(function(k) { attrs[k] = mesh3dAttrs[k]; }); attrs.hoverinfo = extendFlat({}, baseAttrs.hoverinfo, { editType: 'calc', flags: ['x', 'y', 'z', 'u', 'v', 'w', 'norm', 'text', 'name'], dflt: 'x+y+z+norm+text+name' }); attrs.transforms = undefined; module.exports = attrs;