Skip to content

Commit c10eb6f

Browse files
authored
Merge pull request #3098 from plotly/scatterpolargl-2-scatterpolar
Scatterpolargl fixes
2 parents 328bdd4 + 7c0526a commit c10eb6f

File tree

8 files changed

+260
-77
lines changed

8 files changed

+260
-77
lines changed

Diff for: src/plots/polar/index.js

+8
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ function plot(gd) {
5353

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

5760
for(var i = 0; i < oldIds.length; i++) {
5861
var id = oldIds[i];
@@ -66,6 +69,11 @@ function clean(newFullData, newFullLayout, oldFullData, oldFullLayout) {
6669
oldSubplot.clipPaths[k].remove();
6770
}
6871
}
72+
73+
if(mustCleanScene && oldSubplot._scene) {
74+
oldSubplot._scene.destroy();
75+
oldSubplot._scene = null;
76+
}
6977
}
7078
}
7179

Diff for: src/traces/scattergl/index.js

+22-26
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ function calc(gd, trace) {
4242
var xa = AxisIDs.getFromId(gd, trace.xaxis);
4343
var ya = AxisIDs.getFromId(gd, trace.yaxis);
4444
var subplot = fullLayout._plots[trace.xaxis + trace.yaxis];
45-
var count = trace._length;
46-
var count2 = count * 2;
45+
var len = trace._length;
46+
var len2 = len * 2;
4747
var stash = {};
4848
var i, xx, yy;
4949

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

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

6363
if(xa.type === 'log') {
64-
for(i = 0; i < count2; i += 2) {
64+
for(i = 0; i < len2; i += 2) {
6565
positions[i] = xa.c2l(positions[i]);
6666
}
6767
}
6868
if(ya.type === 'log') {
69-
for(i = 1; i < count2; i += 2) {
69+
for(i = 1; i < len2; i += 2) {
7070
positions[i] = ya.c2l(positions[i]);
7171
}
7272
}
@@ -77,8 +77,8 @@ function calc(gd, trace) {
7777
// FIXME: delegate this to webworker
7878
stash.tree = cluster(positions);
7979
} else {
80-
var ids = stash.ids = new Array(count);
81-
for(i = 0; i < count; i++) {
80+
var ids = stash.ids = new Array(len);
81+
for(i = 0; i < len; i++) {
8282
ids[i] = i;
8383
}
8484
}
@@ -92,12 +92,9 @@ function calc(gd, trace) {
9292
// For graphs with very large number of points and array marker.size,
9393
// use average marker size instead to speed things up.
9494
setFirstScatter(fullLayout, trace);
95-
var ppad;
96-
if(count < TOO_MANY_POINTS) {
97-
ppad = calcMarkerSize(trace, count);
98-
} else if(opts.marker) {
99-
ppad = 2 * (opts.marker.sizeAvg || Math.max(opts.marker.size, 3));
100-
}
95+
var ppad = len < TOO_MANY_POINTS ?
96+
calcMarkerSize(trace, len) :
97+
2 * (opts.marker.sizeAvg || Math.max(opts.marker.size, 3));
10198
calcAxisExpansion(gd, trace, xa, ya, x, y, ppad);
10299
if(opts.errorX) expandForErrorBars(trace, xa, opts.errorX);
103100
if(opts.errorY) expandForErrorBars(trace, ya, opts.errorY);
@@ -111,7 +108,7 @@ function calc(gd, trace) {
111108

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

@@ -133,8 +130,6 @@ function calc(gd, trace) {
133130
stash.x = x;
134131
stash.y = y;
135132
stash.positions = positions;
136-
stash.count = count;
137-
138133
scene.count++;
139134

140135
return [{x: false, y: false, t: stash, trace: trace}];
@@ -554,6 +549,7 @@ function plot(gd, subplot, cdata) {
554549
var trace = cd0.trace;
555550
var stash = cd0.t;
556551
var index = stash.index;
552+
var len = trace._length;
557553
var x = stash.x;
558554
var y = stash.y;
559555

@@ -574,7 +570,7 @@ function plot(gd, subplot, cdata) {
574570
selDict[selPts[j]] = 1;
575571
}
576572
var unselPts = [];
577-
for(j = 0; j < stash.count; j++) {
573+
for(j = 0; j < len; j++) {
578574
if(!selDict[j]) unselPts.push(j);
579575
}
580576
scene.unselectBatch[index] = unselPts;
@@ -585,9 +581,9 @@ function plot(gd, subplot, cdata) {
585581
// - spin that in a webworker
586582
// - compute selection from polygons in data coordinates
587583
// (maybe just for linear axes)
588-
var xpx = stash.xpx = new Array(stash.count);
589-
var ypx = stash.ypx = new Array(stash.count);
590-
for(j = 0; j < stash.count; j++) {
584+
var xpx = stash.xpx = new Array(len);
585+
var ypx = stash.ypx = new Array(len);
586+
for(j = 0; j < len; j++) {
591587
xpx[j] = xaxis.c2p(x[j]);
592588
ypx[j] = yaxis.c2p(y[j]);
593589
}
@@ -849,6 +845,7 @@ function selectPoints(searchInfo, selectionTester) {
849845
var selection = [];
850846
var trace = cd[0].trace;
851847
var stash = cd[0].t;
848+
var len = trace._length;
852849
var x = stash.x;
853850
var y = stash.y;
854851
var scene = stash._scene;
@@ -868,7 +865,7 @@ function selectPoints(searchInfo, selectionTester) {
868865
var i;
869866
if(selectionTester !== false && !selectionTester.degenerate) {
870867
els = [], unels = [];
871-
for(i = 0; i < stash.count; i++) {
868+
for(i = 0; i < len; i++) {
872869
if(selectionTester.contains([stash.xpx[i], stash.ypx[i]], false, i, searchInfo)) {
873870
els.push(i);
874871
selection.push({
@@ -882,7 +879,7 @@ function selectPoints(searchInfo, selectionTester) {
882879
}
883880
}
884881
} else {
885-
unels = arrayRange(stash.count);
882+
unels = arrayRange(len);
886883
}
887884

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

917914
function styleTextSelection(cd) {
918915
var cd0 = cd[0];
916+
var trace = cd0.trace;
919917
var stash = cd0.t;
920918
var scene = stash._scene;
921919
var index = stash.index;
@@ -932,8 +930,7 @@ function styleTextSelection(cd) {
932930
var utc = unselOpts.color;
933931
var base = baseOpts.color;
934932
var hasArrayBase = Array.isArray(base);
935-
opts.color = new Array(stash.count);
936-
933+
opts.color = new Array(trace._length);
937934

938935
for(i = 0; i < els.length; i++) {
939936
j = els[i];
@@ -965,7 +962,6 @@ module.exports = {
965962
hoverPoints: hoverPoints,
966963
selectPoints: selectPoints,
967964

968-
sceneOptions: sceneOptions,
969965
sceneUpdate: sceneUpdate,
970966
calcHover: calcHover,
971967

Diff for: src/traces/scatterpolargl/index.js

+81-51
Original file line numberDiff line numberDiff line change
@@ -13,47 +13,63 @@ var isNumeric = require('fast-isnumeric');
1313

1414
var ScatterGl = require('../scattergl');
1515
var calcColorscales = require('../scatter/colorscale_calc');
16+
var calcMarkerSize = require('../scatter/calc').calcMarkerSize;
17+
var convert = require('../scattergl/convert');
18+
19+
var Lib = require('../../lib');
1620
var Axes = require('../../plots/cartesian/axes');
1721
var makeHoverPointText = require('../scatterpolar/hover').makeHoverPointText;
18-
var subTypes = require('../scatter/subtypes');
1922

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

22-
function calc(container, trace) {
23-
var layout = container._fullLayout;
25+
function calc(gd, trace) {
26+
var fullLayout = gd._fullLayout;
2427
var subplotId = trace.subplot;
25-
var radialAxis = layout[subplotId].radialaxis;
26-
var angularAxis = layout[subplotId].angularaxis;
28+
var radialAxis = fullLayout[subplotId].radialaxis;
29+
var angularAxis = fullLayout[subplotId].angularaxis;
2730
var rArray = radialAxis.makeCalcdata(trace, 'r');
2831
var thetaArray = angularAxis.makeCalcdata(trace, 'theta');
32+
var len = trace._length;
2933
var stash = {};
3034

31-
if(trace._length < rArray.length) rArray = rArray.slice(0, trace._length);
32-
if(trace._length < thetaArray.length) thetaArray = thetaArray.slice(0, trace._length);
33-
34-
calcColorscales(trace);
35+
if(len < rArray.length) rArray = rArray.slice(0, len);
36+
if(len < thetaArray.length) thetaArray = thetaArray.slice(0, len);
3537

3638
stash.r = rArray;
3739
stash.theta = thetaArray;
3840

39-
trace._extremes.x = Axes.findExtremes(radialAxis, rArray, {tozero: true});
41+
calcColorscales(trace);
42+
43+
// only compute 'style' options in calc, as position options
44+
// depend on the radial range and must be set in plot
45+
var opts = stash.opts = convert.style(gd, trace);
46+
47+
// For graphs with very large number of points and array marker.size,
48+
// use average marker size instead to speed things up.
49+
var ppad = len < TOO_MANY_POINTS ?
50+
calcMarkerSize(trace, len) :
51+
2 * (opts.marker.sizeAvg || Math.max(opts.marker.size, 3));
52+
trace._extremes.x = Axes.findExtremes(radialAxis, rArray, {ppad: ppad});
4053

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

44-
function plot(container, subplot, cdata) {
57+
function plot(gd, subplot, cdata) {
58+
if(!cdata.length) return;
59+
4560
var radialAxis = subplot.radialAxis;
4661
var angularAxis = subplot.angularAxis;
62+
var scene = ScatterGl.sceneUpdate(gd, subplot);
4763

48-
var scene = ScatterGl.sceneUpdate(container, subplot);
49-
50-
cdata.forEach(function(cdscatter, traceIndex) {
64+
cdata.forEach(function(cdscatter) {
5165
if(!cdscatter || !cdscatter[0] || !cdscatter[0].trace) return;
5266
var cd = cdscatter[0];
5367
var trace = cd.trace;
5468
var stash = cd.t;
69+
var len = trace._length;
5570
var rArray = stash.r;
5671
var thetaArray = stash.theta;
72+
var opts = stash.opts;
5773
var i;
5874

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

70-
var count = rArray.length;
71-
var positions = new Array(count * 2);
72-
var x = Array(count);
73-
var y = Array(count);
86+
var positions = new Array(len * 2);
87+
var x = Array(len);
88+
var y = Array(len);
7489

75-
for(i = 0; i < count; i++) {
90+
for(i = 0; i < len; i++) {
7691
var r = subRArray[i];
7792
var xx, yy;
7893

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

91-
var options = ScatterGl.sceneOptions(container, subplot, trace, positions);
92-
93-
// set flags to create scene renderers
94-
if(options.fill && !scene.fill2d) scene.fill2d = true;
95-
if(options.marker && !scene.scatter2d) scene.scatter2d = true;
96-
if(options.line && !scene.line2d) scene.line2d = true;
97-
if((options.errorX || options.errorY) && !scene.error2d) scene.error2d = true;
98-
if(options.text && !scene.glText) scene.glText = true;
99-
100106
stash.tree = cluster(positions);
101107

102108
// FIXME: see scattergl.js#109
103-
if(options.marker && count >= TOO_MANY_POINTS) {
104-
options.marker.cluster = stash.tree;
109+
if(opts.marker && len >= TOO_MANY_POINTS) {
110+
opts.marker.cluster = stash.tree;
105111
}
106112

107-
// bring positions to selected/unselected options
108-
if(subTypes.hasMarkers(trace)) {
109-
options.markerSel.positions = options.markerUnsel.positions = options.marker.positions;
113+
if(opts.marker) {
114+
opts.markerSel.positions = opts.markerUnsel.positions = opts.marker.positions = positions;
110115
}
111116

112-
// save scene options batch
113-
scene.lineOptions.push(options.line);
114-
scene.errorXOptions.push(options.errorX);
115-
scene.errorYOptions.push(options.errorY);
116-
scene.fillOptions.push(options.fill);
117-
scene.markerOptions.push(options.marker);
118-
scene.markerSelectedOptions.push(options.markerSel);
119-
scene.markerUnselectedOptions.push(options.markerUnsel);
120-
scene.textOptions.push(options.text);
121-
scene.textSelectedOptions.push(options.textSel);
122-
scene.textUnselectedOptions.push(options.textUnsel);
123-
scene.count = cdata.length;
124-
125-
// stash scene ref
126-
stash._scene = scene;
127-
stash.index = traceIndex;
117+
if(opts.line && positions.length > 1) {
118+
Lib.extendFlat(
119+
opts.line,
120+
convert.linePositions(gd, trace, positions)
121+
);
122+
}
123+
124+
if(opts.text) {
125+
Lib.extendFlat(
126+
opts.text,
127+
{positions: positions},
128+
convert.textPosition(gd, trace, opts.text, opts.marker)
129+
);
130+
Lib.extendFlat(
131+
opts.textSel,
132+
{positions: positions},
133+
convert.textPosition(gd, trace, opts.text, opts.markerSel)
134+
);
135+
Lib.extendFlat(
136+
opts.textUnsel,
137+
{positions: positions},
138+
convert.textPosition(gd, trace, opts.text, opts.markerUnsel)
139+
);
140+
}
141+
142+
if(opts.fill && !scene.fill2d) scene.fill2d = true;
143+
if(opts.marker && !scene.scatter2d) scene.scatter2d = true;
144+
if(opts.line && !scene.line2d) scene.line2d = true;
145+
if(opts.text && !scene.glText) scene.glText = true;
146+
147+
scene.lineOptions.push(opts.line);
148+
scene.fillOptions.push(opts.fill);
149+
scene.markerOptions.push(opts.marker);
150+
scene.markerSelectedOptions.push(opts.markerSel);
151+
scene.markerUnselectedOptions.push(opts.markerUnsel);
152+
scene.textOptions.push(opts.text);
153+
scene.textSelectedOptions.push(opts.textSel);
154+
scene.textUnselectedOptions.push(opts.textUnsel);
155+
128156
stash.x = x;
129157
stash.y = y;
130158
stash.rawx = x;
131159
stash.rawy = y;
132160
stash.r = rArray;
133161
stash.theta = thetaArray;
134162
stash.positions = positions;
135-
stash.count = count;
163+
stash._scene = scene;
164+
stash.index = scene.count;
165+
scene.count++;
136166
});
137167

138-
return ScatterGl.plot(container, subplot, cdata);
168+
return ScatterGl.plot(gd, subplot, cdata);
139169
}
140170

141171
function hoverPoints(pointData, xval, yval, hovermode) {

Diff for: test/image/baselines/glpolar_scatter.png

-6.02 KB
Loading

Diff for: test/image/baselines/glpolar_style.png

4.29 KB
Loading

Diff for: test/image/baselines/glpolar_subplots.png

49 Bytes
Loading

Diff for: test/image/baselines/polar_r0dr-theta0dtheta.png

2.97 KB
Loading

0 commit comments

Comments
 (0)