plotly.js
Version:
The open source javascript graphing library that powers plotly
144 lines (114 loc) • 4.29 kB
JavaScript
'use strict';
var conePlot = require('../../../stackgl_modules').gl_cone3d;
var createConeMesh = require('../../../stackgl_modules').gl_cone3d.createConeMesh;
var simpleMap = require('../../lib').simpleMap;
var parseColorScale = require('../../lib/gl_format_color').parseColorScale;
var extractOpts = require('../../components/colorscale').extractOpts;
var isArrayOrTypedArray = require('../../lib').isArrayOrTypedArray;
var zip3 = require('../../plots/gl3d/zip3');
function Cone(scene, uid) {
this.scene = scene;
this.uid = uid;
this.mesh = null;
this.data = null;
}
var proto = Cone.prototype;
proto.handlePick = function(selection) {
if(selection.object === this.mesh) {
var selectIndex = selection.index = selection.data.index;
var xx = this.data.x[selectIndex];
var yy = this.data.y[selectIndex];
var zz = this.data.z[selectIndex];
var uu = this.data.u[selectIndex];
var vv = this.data.v[selectIndex];
var ww = this.data.w[selectIndex];
selection.traceCoordinate = [
xx, yy, zz,
uu, vv, ww,
Math.sqrt(uu * uu + vv * vv + ww * ww)
];
var text = this.data.hovertext || this.data.text;
if(isArrayOrTypedArray(text) && text[selectIndex] !== undefined) {
selection.textLabel = text[selectIndex];
} else if(text) {
selection.textLabel = text;
}
return true;
}
};
var axisName2scaleIndex = {xaxis: 0, yaxis: 1, zaxis: 2};
var anchor2coneOffset = {tip: 1, tail: 0, cm: 0.25, center: 0.5};
var anchor2coneSpan = {tip: 1, tail: 1, cm: 0.75, center: 0.5};
function convert(scene, trace) {
var sceneLayout = scene.fullSceneLayout;
var dataScale = scene.dataScale;
var coneOpts = {};
function toDataCoords(arr, axisName) {
var ax = sceneLayout[axisName];
var scale = dataScale[axisName2scaleIndex[axisName]];
return simpleMap(arr, function(v) { return ax.d2l(v) * scale; });
}
coneOpts.vectors = zip3(
toDataCoords(trace.u, 'xaxis'),
toDataCoords(trace.v, 'yaxis'),
toDataCoords(trace.w, 'zaxis'),
trace._len
);
coneOpts.positions = zip3(
toDataCoords(trace.x, 'xaxis'),
toDataCoords(trace.y, 'yaxis'),
toDataCoords(trace.z, 'zaxis'),
trace._len
);
var cOpts = extractOpts(trace);
coneOpts.colormap = parseColorScale(trace);
coneOpts.vertexIntensityBounds = [cOpts.min / trace._normMax, cOpts.max / trace._normMax];
coneOpts.coneOffset = anchor2coneOffset[trace.anchor];
var sizemode = trace.sizemode;
if(sizemode === 'scaled') {
// unitless sizeref
coneOpts.coneSize = trace.sizeref || 0.5;
} else if(sizemode === 'absolute') {
// sizeref here has unit of velocity
coneOpts.coneSize = trace.sizeref && trace._normMax ?
trace.sizeref / trace._normMax :
0.5;
} else if(sizemode === 'raw') {
coneOpts.coneSize = trace.sizeref;
}
coneOpts.coneSizemode = sizemode;
var meshData = conePlot(coneOpts);
// pass gl-mesh3d lighting attributes
var lp = trace.lightposition;
meshData.lightPosition = [lp.x, lp.y, lp.z];
meshData.ambient = trace.lighting.ambient;
meshData.diffuse = trace.lighting.diffuse;
meshData.specular = trace.lighting.specular;
meshData.roughness = trace.lighting.roughness;
meshData.fresnel = trace.lighting.fresnel;
meshData.opacity = trace.opacity;
// stash autorange pad value
trace._pad = anchor2coneSpan[trace.anchor] * meshData.vectorScale * meshData.coneScale * trace._normMax;
return meshData;
}
proto.update = function(data) {
this.data = data;
var meshData = convert(this.scene, data);
this.mesh.update(meshData);
};
proto.dispose = function() {
this.scene.glplot.remove(this.mesh);
this.mesh.dispose();
};
function createConeTrace(scene, data) {
var gl = scene.glplot.gl;
var meshData = convert(scene, data);
var mesh = createConeMesh(gl, meshData);
var cone = new Cone(scene, data.uid);
cone.mesh = mesh;
cone.data = data;
mesh._trace = cone;
scene.glplot.add(mesh);
return cone;
}
module.exports = createConeTrace;