Skip to content

Commit

Permalink
Merge pull request #3098 from plotly/scatterpolargl-2-scatterpolar
Browse files Browse the repository at this point in the history
Scatterpolargl fixes
  • Loading branch information
etpinard authored Oct 24, 2018
2 parents 328bdd4 + 7c0526a commit c10eb6f
Show file tree
Hide file tree
Showing 8 changed files with 260 additions and 77 deletions.
8 changes: 8 additions & 0 deletions src/plots/polar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ function plot(gd) {

function clean(newFullData, newFullLayout, oldFullData, oldFullLayout) {
var oldIds = oldFullLayout._subplots[name] || [];
var hadGl = (oldFullLayout._has && oldFullLayout._has('gl'));
var hasGl = (newFullLayout._has && newFullLayout._has('gl'));
var mustCleanScene = hadGl && !hasGl;

for(var i = 0; i < oldIds.length; i++) {
var id = oldIds[i];
Expand All @@ -66,6 +69,11 @@ function clean(newFullData, newFullLayout, oldFullData, oldFullLayout) {
oldSubplot.clipPaths[k].remove();
}
}

if(mustCleanScene && oldSubplot._scene) {
oldSubplot._scene.destroy();
oldSubplot._scene = null;
}
}
}

Expand Down
48 changes: 22 additions & 26 deletions src/traces/scattergl/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ function calc(gd, trace) {
var xa = AxisIDs.getFromId(gd, trace.xaxis);
var ya = AxisIDs.getFromId(gd, trace.yaxis);
var subplot = fullLayout._plots[trace.xaxis + trace.yaxis];
var count = trace._length;
var count2 = count * 2;
var len = trace._length;
var len2 = len * 2;
var stash = {};
var i, xx, yy;

Expand All @@ -52,21 +52,21 @@ function calc(gd, trace) {

// we need hi-precision for scatter2d,
// regl-scatter2d uses NaNs for bad/missing values
var positions = new Array(count2);
for(i = 0; i < count; i++) {
var positions = new Array(len2);
for(i = 0; i < len; i++) {
xx = x[i];
yy = y[i];
positions[i * 2] = xx === BADNUM ? NaN : xx;
positions[i * 2 + 1] = yy === BADNUM ? NaN : yy;
}

if(xa.type === 'log') {
for(i = 0; i < count2; i += 2) {
for(i = 0; i < len2; i += 2) {
positions[i] = xa.c2l(positions[i]);
}
}
if(ya.type === 'log') {
for(i = 1; i < count2; i += 2) {
for(i = 1; i < len2; i += 2) {
positions[i] = ya.c2l(positions[i]);
}
}
Expand All @@ -77,8 +77,8 @@ function calc(gd, trace) {
// FIXME: delegate this to webworker
stash.tree = cluster(positions);
} else {
var ids = stash.ids = new Array(count);
for(i = 0; i < count; i++) {
var ids = stash.ids = new Array(len);
for(i = 0; i < len; i++) {
ids[i] = i;
}
}
Expand All @@ -92,12 +92,9 @@ function calc(gd, trace) {
// For graphs with very large number of points and array marker.size,
// use average marker size instead to speed things up.
setFirstScatter(fullLayout, trace);
var ppad;
if(count < TOO_MANY_POINTS) {
ppad = calcMarkerSize(trace, count);
} else if(opts.marker) {
ppad = 2 * (opts.marker.sizeAvg || Math.max(opts.marker.size, 3));
}
var ppad = len < TOO_MANY_POINTS ?
calcMarkerSize(trace, len) :
2 * (opts.marker.sizeAvg || Math.max(opts.marker.size, 3));
calcAxisExpansion(gd, trace, xa, ya, x, y, ppad);
if(opts.errorX) expandForErrorBars(trace, xa, opts.errorX);
if(opts.errorY) expandForErrorBars(trace, ya, opts.errorY);
Expand All @@ -111,7 +108,7 @@ function calc(gd, trace) {

// FIXME: organize it in a more appropriate manner, probably in sceneOptions
// put point-cluster instance for optimized regl calc
if(opts.marker && count >= TOO_MANY_POINTS) {
if(opts.marker && len >= TOO_MANY_POINTS) {
opts.marker.cluster = stash.tree;
}

Expand All @@ -133,8 +130,6 @@ function calc(gd, trace) {
stash.x = x;
stash.y = y;
stash.positions = positions;
stash.count = count;

scene.count++;

return [{x: false, y: false, t: stash, trace: trace}];
Expand Down Expand Up @@ -554,6 +549,7 @@ function plot(gd, subplot, cdata) {
var trace = cd0.trace;
var stash = cd0.t;
var index = stash.index;
var len = trace._length;
var x = stash.x;
var y = stash.y;

Expand All @@ -574,7 +570,7 @@ function plot(gd, subplot, cdata) {
selDict[selPts[j]] = 1;
}
var unselPts = [];
for(j = 0; j < stash.count; j++) {
for(j = 0; j < len; j++) {
if(!selDict[j]) unselPts.push(j);
}
scene.unselectBatch[index] = unselPts;
Expand All @@ -585,9 +581,9 @@ function plot(gd, subplot, cdata) {
// - spin that in a webworker
// - compute selection from polygons in data coordinates
// (maybe just for linear axes)
var xpx = stash.xpx = new Array(stash.count);
var ypx = stash.ypx = new Array(stash.count);
for(j = 0; j < stash.count; j++) {
var xpx = stash.xpx = new Array(len);
var ypx = stash.ypx = new Array(len);
for(j = 0; j < len; j++) {
xpx[j] = xaxis.c2p(x[j]);
ypx[j] = yaxis.c2p(y[j]);
}
Expand Down Expand Up @@ -849,6 +845,7 @@ function selectPoints(searchInfo, selectionTester) {
var selection = [];
var trace = cd[0].trace;
var stash = cd[0].t;
var len = trace._length;
var x = stash.x;
var y = stash.y;
var scene = stash._scene;
Expand All @@ -868,7 +865,7 @@ function selectPoints(searchInfo, selectionTester) {
var i;
if(selectionTester !== false && !selectionTester.degenerate) {
els = [], unels = [];
for(i = 0; i < stash.count; i++) {
for(i = 0; i < len; i++) {
if(selectionTester.contains([stash.xpx[i], stash.ypx[i]], false, i, searchInfo)) {
els.push(i);
selection.push({
Expand All @@ -882,7 +879,7 @@ function selectPoints(searchInfo, selectionTester) {
}
}
} else {
unels = arrayRange(stash.count);
unels = arrayRange(len);
}

// make sure selectBatch is created
Expand Down Expand Up @@ -916,6 +913,7 @@ function selectPoints(searchInfo, selectionTester) {

function styleTextSelection(cd) {
var cd0 = cd[0];
var trace = cd0.trace;
var stash = cd0.t;
var scene = stash._scene;
var index = stash.index;
Expand All @@ -932,8 +930,7 @@ function styleTextSelection(cd) {
var utc = unselOpts.color;
var base = baseOpts.color;
var hasArrayBase = Array.isArray(base);
opts.color = new Array(stash.count);

opts.color = new Array(trace._length);

for(i = 0; i < els.length; i++) {
j = els[i];
Expand Down Expand Up @@ -965,7 +962,6 @@ module.exports = {
hoverPoints: hoverPoints,
selectPoints: selectPoints,

sceneOptions: sceneOptions,
sceneUpdate: sceneUpdate,
calcHover: calcHover,

Expand Down
132 changes: 81 additions & 51 deletions src/traces/scatterpolargl/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,47 +13,63 @@ var isNumeric = require('fast-isnumeric');

var ScatterGl = require('../scattergl');
var calcColorscales = require('../scatter/colorscale_calc');
var calcMarkerSize = require('../scatter/calc').calcMarkerSize;
var convert = require('../scattergl/convert');

var Lib = require('../../lib');
var Axes = require('../../plots/cartesian/axes');
var makeHoverPointText = require('../scatterpolar/hover').makeHoverPointText;
var subTypes = require('../scatter/subtypes');

var TOO_MANY_POINTS = require('../scattergl/constants').TOO_MANY_POINTS;

function calc(container, trace) {
var layout = container._fullLayout;
function calc(gd, trace) {
var fullLayout = gd._fullLayout;
var subplotId = trace.subplot;
var radialAxis = layout[subplotId].radialaxis;
var angularAxis = layout[subplotId].angularaxis;
var radialAxis = fullLayout[subplotId].radialaxis;
var angularAxis = fullLayout[subplotId].angularaxis;
var rArray = radialAxis.makeCalcdata(trace, 'r');
var thetaArray = angularAxis.makeCalcdata(trace, 'theta');
var len = trace._length;
var stash = {};

if(trace._length < rArray.length) rArray = rArray.slice(0, trace._length);
if(trace._length < thetaArray.length) thetaArray = thetaArray.slice(0, trace._length);

calcColorscales(trace);
if(len < rArray.length) rArray = rArray.slice(0, len);
if(len < thetaArray.length) thetaArray = thetaArray.slice(0, len);

stash.r = rArray;
stash.theta = thetaArray;

trace._extremes.x = Axes.findExtremes(radialAxis, rArray, {tozero: true});
calcColorscales(trace);

// only compute 'style' options in calc, as position options
// depend on the radial range and must be set in plot
var opts = stash.opts = convert.style(gd, trace);

// For graphs with very large number of points and array marker.size,
// use average marker size instead to speed things up.
var ppad = len < TOO_MANY_POINTS ?
calcMarkerSize(trace, len) :
2 * (opts.marker.sizeAvg || Math.max(opts.marker.size, 3));
trace._extremes.x = Axes.findExtremes(radialAxis, rArray, {ppad: ppad});

return [{x: false, y: false, t: stash, trace: trace}];
}

function plot(container, subplot, cdata) {
function plot(gd, subplot, cdata) {
if(!cdata.length) return;

var radialAxis = subplot.radialAxis;
var angularAxis = subplot.angularAxis;
var scene = ScatterGl.sceneUpdate(gd, subplot);

var scene = ScatterGl.sceneUpdate(container, subplot);

cdata.forEach(function(cdscatter, traceIndex) {
cdata.forEach(function(cdscatter) {
if(!cdscatter || !cdscatter[0] || !cdscatter[0].trace) return;
var cd = cdscatter[0];
var trace = cd.trace;
var stash = cd.t;
var len = trace._length;
var rArray = stash.r;
var thetaArray = stash.theta;
var opts = stash.opts;
var i;

var subRArray = rArray.slice();
Expand All @@ -67,12 +83,11 @@ function plot(container, subplot, cdata) {
}
}

var count = rArray.length;
var positions = new Array(count * 2);
var x = Array(count);
var y = Array(count);
var positions = new Array(len * 2);
var x = Array(len);
var y = Array(len);

for(i = 0; i < count; i++) {
for(i = 0; i < len; i++) {
var r = subRArray[i];
var xx, yy;

Expand All @@ -88,54 +103,69 @@ function plot(container, subplot, cdata) {
y[i] = positions[i * 2 + 1] = yy;
}

var options = ScatterGl.sceneOptions(container, subplot, trace, positions);

// set flags to create scene renderers
if(options.fill && !scene.fill2d) scene.fill2d = true;
if(options.marker && !scene.scatter2d) scene.scatter2d = true;
if(options.line && !scene.line2d) scene.line2d = true;
if((options.errorX || options.errorY) && !scene.error2d) scene.error2d = true;
if(options.text && !scene.glText) scene.glText = true;

stash.tree = cluster(positions);

// FIXME: see scattergl.js#109
if(options.marker && count >= TOO_MANY_POINTS) {
options.marker.cluster = stash.tree;
if(opts.marker && len >= TOO_MANY_POINTS) {
opts.marker.cluster = stash.tree;
}

// bring positions to selected/unselected options
if(subTypes.hasMarkers(trace)) {
options.markerSel.positions = options.markerUnsel.positions = options.marker.positions;
if(opts.marker) {
opts.markerSel.positions = opts.markerUnsel.positions = opts.marker.positions = positions;
}

// save scene options batch
scene.lineOptions.push(options.line);
scene.errorXOptions.push(options.errorX);
scene.errorYOptions.push(options.errorY);
scene.fillOptions.push(options.fill);
scene.markerOptions.push(options.marker);
scene.markerSelectedOptions.push(options.markerSel);
scene.markerUnselectedOptions.push(options.markerUnsel);
scene.textOptions.push(options.text);
scene.textSelectedOptions.push(options.textSel);
scene.textUnselectedOptions.push(options.textUnsel);
scene.count = cdata.length;

// stash scene ref
stash._scene = scene;
stash.index = traceIndex;
if(opts.line && positions.length > 1) {
Lib.extendFlat(
opts.line,
convert.linePositions(gd, trace, positions)
);
}

if(opts.text) {
Lib.extendFlat(
opts.text,
{positions: positions},
convert.textPosition(gd, trace, opts.text, opts.marker)
);
Lib.extendFlat(
opts.textSel,
{positions: positions},
convert.textPosition(gd, trace, opts.text, opts.markerSel)
);
Lib.extendFlat(
opts.textUnsel,
{positions: positions},
convert.textPosition(gd, trace, opts.text, opts.markerUnsel)
);
}

if(opts.fill && !scene.fill2d) scene.fill2d = true;
if(opts.marker && !scene.scatter2d) scene.scatter2d = true;
if(opts.line && !scene.line2d) scene.line2d = true;
if(opts.text && !scene.glText) scene.glText = true;

scene.lineOptions.push(opts.line);
scene.fillOptions.push(opts.fill);
scene.markerOptions.push(opts.marker);
scene.markerSelectedOptions.push(opts.markerSel);
scene.markerUnselectedOptions.push(opts.markerUnsel);
scene.textOptions.push(opts.text);
scene.textSelectedOptions.push(opts.textSel);
scene.textUnselectedOptions.push(opts.textUnsel);

stash.x = x;
stash.y = y;
stash.rawx = x;
stash.rawy = y;
stash.r = rArray;
stash.theta = thetaArray;
stash.positions = positions;
stash.count = count;
stash._scene = scene;
stash.index = scene.count;
scene.count++;
});

return ScatterGl.plot(container, subplot, cdata);
return ScatterGl.plot(gd, subplot, cdata);
}

function hoverPoints(pointData, xval, yval, hovermode) {
Expand Down
Binary file modified test/image/baselines/glpolar_scatter.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/glpolar_style.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/glpolar_subplots.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/polar_r0dr-theta0dtheta.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit c10eb6f

Please sign in to comment.