'use strict'; var Lib = require('../../lib'); var colorscaleCalc = require('../../components/colorscale/calc'); function calc(gd, trace) { trace._len = Math.min( trace.u.length, trace.v.length, trace.w.length, trace.x.length, trace.y.length, trace.z.length ); trace._u = filter(trace.u, trace._len); trace._v = filter(trace.v, trace._len); trace._w = filter(trace.w, trace._len); trace._x = filter(trace.x, trace._len); trace._y = filter(trace.y, trace._len); trace._z = filter(trace.z, 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 slen = 0; var startx, starty, startz; if(trace.starts) { startx = filter(trace.starts.x || []); starty = filter(trace.starts.y || []); startz = filter(trace.starts.z || []); slen = Math.min(startx.length, starty.length, startz.length); } trace._startsX = startx || []; trace._startsY = starty || []; trace._startsZ = startz || []; var normMax = 0; var normMin = Infinity; var i; for(i = 0; i < trace._len; i++) { var u = trace._u[i]; var v = trace._v[i]; var w = trace._w[i]; var norm = Math.sqrt(u * u + v * v + w * w); normMax = Math.max(normMax, norm); normMin = Math.min(normMin, norm); } colorscaleCalc(gd, trace, { vals: [normMin, normMax], containerStr: '', cLetter: 'c' }); for(i = 0; i < slen; i++) { var sx = startx[i]; grid.xMax = Math.max(grid.xMax, sx); grid.xMin = Math.min(grid.xMin, sx); var sy = starty[i]; grid.yMax = Math.max(grid.yMax, sy); grid.yMin = Math.min(grid.yMin, sy); var sz = startz[i]; grid.zMax = Math.max(grid.zMax, sz); grid.zMin = Math.min(grid.zMin, sz); } trace._slen = slen; trace._normMax = normMax; trace._xbnds = [grid.xMin, grid.xMax]; trace._ybnds = [grid.yMin, grid.yMax]; trace._zbnds = [grid.zMin, grid.zMax]; } function processGrid(trace) { var x = trace._x; var y = trace._y; var z = trace._z; var len = trace._len; var i, j, k; var xMax = -Infinity; var xMin = Infinity; var yMax = -Infinity; var yMin = Infinity; var zMax = -Infinity; var zMin = Infinity; var gridFill = ''; var filledX; var filledY; var filledZ; var firstX, lastX; var firstY, lastY; var firstZ, lastZ; if(len) { firstX = x[0]; firstY = y[0]; firstZ = z[0]; } if(len > 1) { lastX = x[len - 1]; lastY = y[len - 1]; lastZ = z[len - 1]; } for(i = 0; i < len; i++) { xMax = Math.max(xMax, x[i]); xMin = Math.min(xMin, x[i]); yMax = Math.max(yMax, y[i]); yMin = Math.min(yMin, y[i]); zMax = Math.max(zMax, z[i]); zMin = Math.min(zMin, z[i]); if(!filledX && x[i] !== firstX) { filledX = true; gridFill += 'x'; } if(!filledY && y[i] !== firstY) { filledY = true; gridFill += 'y'; } if(!filledZ && z[i] !== firstZ) { filledZ = true; gridFill += 'z'; } } // fill if not filled - case of having dimension(s) with one item if(!filledX) gridFill += 'x'; if(!filledY) gridFill += 'y'; if(!filledZ) gridFill += 'z'; var Xs = distinctVals(trace._x); var Ys = distinctVals(trace._y); var Zs = distinctVals(trace._z); gridFill = gridFill.replace('x', (firstX > lastX ? '-' : '+') + 'x'); gridFill = gridFill.replace('y', (firstY > lastY ? '-' : '+') + 'y'); gridFill = gridFill.replace('z', (firstZ > lastZ ? '-' : '+') + 'z'); var empty = function() { len = 0; Xs = []; Ys = []; Zs = []; }; // Over-specified mesh case, this would error in tube2mesh if(!len || len < Xs.length * Ys.length * Zs.length) empty(); var getArray = function(c) { return c === 'x' ? x : c === 'y' ? y : z; }; var getVals = function(c) { return c === 'x' ? Xs : c === 'y' ? Ys : Zs; }; var getDir = function(c) { return c[len - 1] < c[0] ? -1 : 1; }; var arrK = getArray(gridFill[1]); var arrJ = getArray(gridFill[3]); var arrI = getArray(gridFill[5]); var nk = getVals(gridFill[1]).length; var nj = getVals(gridFill[3]).length; var ni = getVals(gridFill[5]).length; var arbitrary = false; var getIndex = function(_i, _j, _k) { return nk * (nj * _i + _j) + _k; }; var dirK = getDir(getArray(gridFill[1])); var dirJ = getDir(getArray(gridFill[3])); var dirI = getDir(getArray(gridFill[5])); for(i = 0; i < ni - 1; i++) { for(j = 0; j < nj - 1; j++) { for(k = 0; k < nk - 1; k++) { var q000 = getIndex(i, j, k); var q001 = getIndex(i, j, k + 1); var q010 = getIndex(i, j + 1, k); var q100 = getIndex(i + 1, j, k); if( !(arrK[q000] * dirK < arrK[q001] * dirK) || !(arrJ[q000] * dirJ < arrJ[q010] * dirJ) || !(arrI[q000] * dirI < arrI[q100] * dirI) ) { arbitrary = true; } if(arbitrary) break; } if(arbitrary) break; } if(arbitrary) break; } if(arbitrary) { Lib.warn('Encountered arbitrary coordinates! Unable to input data grid.'); empty(); } return { xMin: xMin, yMin: yMin, zMin: zMin, xMax: xMax, yMax: yMax, zMax: zMax, Xs: Xs, Ys: Ys, Zs: Zs, len: len, fill: gridFill }; } function distinctVals(col) { return Lib.distinctVals(col).vals; } function filter(arr, len) { if(len === undefined) len = arr.length; // no need for casting typed arrays to numbers if(Lib.isTypedArray(arr)) return arr.subarray(0, len); var values = []; for(var i = 0; i < len; i++) { values[i] = +arr[i]; } return values; } module.exports = { calc: calc, filter: filter, processGrid: processGrid };