Skip to content

Commit d3ff96b

Browse files
authored
Merge pull request #2499 from plotly/point-cluster-dev
Point cluster dev
2 parents c385218 + 0d74d2f commit d3ff96b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+119
-47
lines changed

package-lock.json

+48-29
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@
8686
"glslify": "^6.1.1",
8787
"has-hover": "^1.0.1",
8888
"has-passive-events": "^1.0.0",
89-
"kdgrass": "^1.0.1",
9089
"mapbox-gl": "0.44.1",
9190
"matrix-camera-controller": "^2.1.3",
9291
"mouse-change": "^1.4.0",
@@ -96,11 +95,12 @@
9695
"ndarray-fill": "^1.0.2",
9796
"ndarray-homography": "^1.0.0",
9897
"ndarray-ops": "^1.2.2",
98+
"point-cluster": "^3.1.2",
9999
"polybooljs": "^1.2.0",
100100
"regl": "^1.3.1",
101101
"regl-error2d": "^2.0.3",
102102
"regl-line2d": "^2.1.5",
103-
"regl-scatter2d": "^2.1.17",
103+
"regl-scatter2d": "^3.0.0",
104104
"right-now": "^1.0.0",
105105
"robust-orientation": "^1.1.3",
106106
"sane-topojson": "^2.0.0",

src/traces/scattergl/convert.js

+9
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ var subTypes = require('../scatter/subtypes');
2121
var makeBubbleSizeFn = require('../scatter/make_bubble_size_func');
2222

2323
var constants = require('./constants');
24+
var DESELECTDIM = require('../../constants/interactions').DESELECTDIM;
2425

2526
function convertStyle(gd, trace) {
2627
var i;
@@ -41,6 +42,14 @@ function convertStyle(gd, trace) {
4142
opts.marker = convertMarkerStyle(trace);
4243
opts.selected = convertMarkerSelection(trace, trace.selected);
4344
opts.unselected = convertMarkerSelection(trace, trace.unselected);
45+
46+
if(!trace.unselected && Array.isArray(trace.marker.opacity)) {
47+
var mo = trace.marker.opacity;
48+
opts.unselected.opacity = new Array(mo.length);
49+
for(i = 0; i < mo.length; i++) {
50+
opts.unselected.opacity[i] = DESELECTDIM * mo[i];
51+
}
52+
}
4453
}
4554

4655
if(subTypes.hasLines(trace)) {

src/traces/scattergl/index.js

+9-6
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ var createRegl = require('regl');
1212
var createScatter = require('regl-scatter2d');
1313
var createLine = require('regl-line2d');
1414
var createError = require('regl-error2d');
15-
var kdtree = require('kdgrass');
15+
var cluster = require('point-cluster');
1616
var arrayRange = require('array-range');
1717

1818
var Registry = require('../../registry');
@@ -72,7 +72,7 @@ function calc(gd, trace) {
7272
// and it is also
7373
if(xa.type !== 'log' && ya.type !== 'log') {
7474
// FIXME: delegate this to webworker
75-
stash.tree = kdtree(positions, 512);
75+
stash.tree = cluster(positions);
7676
} else {
7777
var ids = stash.ids = new Array(count);
7878
for(i = 0; i < count; i++) {
@@ -104,6 +104,12 @@ function calc(gd, trace) {
104104
if(opts.line && !scene.line2d) scene.line2d = true;
105105
if((opts.errorX || opts.errorY) && !scene.error2d) scene.error2d = true;
106106

107+
// FIXME: organize it in a more appropriate manner, probably in sceneOptions
108+
// put point-cluster instance for optimized regl calc
109+
if(opts.marker && count >= TOO_MANY_POINTS) {
110+
opts.marker.cluster = stash.tree;
111+
}
112+
107113
// save scene opts batch
108114
scene.lineOptions.push(opts.line);
109115
scene.errorXOptions.push(opts.errorX);
@@ -547,10 +553,7 @@ function plot(gd, subplot, cdata) {
547553
// create select2d
548554
if(!scene.select2d) {
549555
// create scatter instance by cloning scatter2d
550-
scene.select2d = createScatter(
551-
fullLayout._glcanvas.data()[1].regl,
552-
{clone: scene.scatter2d}
553-
);
556+
scene.select2d = createScatter(fullLayout._glcanvas.data()[1].regl);
554557
}
555558

556559
if(scene.scatter2d && scene.selectBatch && scene.selectBatch.length) {

src/traces/scatterpolargl/index.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
'use strict';
1010

11-
var kdtree = require('kdgrass');
11+
var cluster = require('point-cluster');
1212
var isNumeric = require('fast-isnumeric');
1313

1414
var ScatterGl = require('../scattergl');
@@ -17,6 +17,8 @@ var Axes = require('../../plots/cartesian/axes');
1717
var makeHoverPointText = require('../scatterpolar/hover').makeHoverPointText;
1818
var subTypes = require('../scatter/subtypes');
1919

20+
var TOO_MANY_POINTS = require('../scattergl/constants').TOO_MANY_POINTS;
21+
2022
function calc(container, trace) {
2123
var layout = container._fullLayout;
2224
var subplotId = trace.subplot;
@@ -106,6 +108,13 @@ function plot(container, subplot, cdata) {
106108
if(options.line && !scene.line2d) scene.line2d = true;
107109
if((options.errorX || options.errorY) && !scene.error2d) scene.error2d = true;
108110

111+
stash.tree = cluster(positions);
112+
113+
// FIXME: see scattergl.js#109
114+
if(options.marker && count >= TOO_MANY_POINTS) {
115+
options.marker.cluster = stash.tree;
116+
}
117+
109118
// bring positions to selected/unselected options
110119
if(subTypes.hasMarkers(trace)) {
111120
options.selected.positions = options.unselected.positions = options.marker.positions;
@@ -132,7 +141,6 @@ function plot(container, subplot, cdata) {
132141
stash.theta = thetaArray;
133142
stash.positions = positions;
134143
stash.count = count;
135-
stash.tree = kdtree(positions, 512);
136144
});
137145

138146
return ScatterGl.plot(container, subplot, cdata);

tasks/test_syntax.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ function assertES5() {
282282
});
283283

284284
var files = constants.partialBundlePaths.map(function(f) { return f.dist; });
285-
files.unshift(constants.pathToPlotlyDist);
285+
files.unshift(constants.pathToPlotlyBuild, constants.pathToPlotlyDist);
286286

287287
var report = cli.executeOnFiles(files);
288288
var formatter = cli.getFormatter();

test/image/baselines/gl2d_14.png

-469 Bytes

test/image/baselines/gl2d_17.png

-64 Bytes
-99 Bytes
32 Bytes
32 Bytes
-6 Bytes
53 Bytes
-15 Bytes
-12 Bytes
-13 Bytes
-40 Bytes
-22 Bytes
-13 Bytes

test/image/baselines/gl2d_fonts.png

-42 Bytes
-43 Bytes
-67 Bytes
197 Bytes
-26 Bytes
-25 Bytes
329 Bytes
18.5 KB
-81 Bytes
-24 Bytes
-32 Bytes
-16 Bytes
-22 Bytes
-704 Bytes
-38 Bytes
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"data": [{
3+
"name": "array marker opacity edge case",
4+
"type": "scattergl",
5+
"mode": "markers",
6+
"x": [1, 2, 3, 4, 5, 6],
7+
"y": [1, 3, 2, 4, 5, 7],
8+
"marker": {
9+
"size": 20,
10+
"opacity": [0.9, 0.8, 0.7, 1, 0.6, 0.8]
11+
},
12+
"selectedpoints": [1, 4, 2]
13+
}, {
14+
"name": "array marker opacity + set unselected.marker.opacity",
15+
"type": "scattergl",
16+
"mode": "markers",
17+
"x": [1, 2, 3, 4, 5, 6],
18+
"y": [3, 5, 4, 6, 7, 9],
19+
"marker": {
20+
"size": 20,
21+
"opacity": [0.9, 0.8, 0.7, 1, 0.6, 0.8]
22+
},
23+
"unselected": {
24+
"marker": {
25+
"opacity": 0
26+
}
27+
},
28+
"selectedpoints": [1, 4, 2]
29+
}],
30+
"layout": {
31+
"showlegend": false
32+
}
33+
}

test/jasmine/tests/gl2d_click_test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ var mock4 = {
6464
layout: {}
6565
};
6666

67-
describe('@gl Test hover and click interactions', function() {
67+
describe('@gl @flaky Test hover and click interactions', function() {
6868
var gd;
6969

7070
function makeHoverFn(gd, x, y) {

test/jasmine/tests/gl2d_plot_interact_test.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ describe('@gl Test gl2d plots', function() {
518518
.then(done);
519519
});
520520

521-
it('supports 1D and 2D Zoom', function(done) {
521+
it('@flaky supports 1D and 2D Zoom', function(done) {
522522
var centerX;
523523
var centerY;
524524

@@ -571,7 +571,7 @@ describe('@gl Test gl2d plots', function() {
571571
.then(done);
572572
});
573573

574-
it('supports axis constraints with zoom', function(done) {
574+
it('@flaky supports axis constraints with zoom', function(done) {
575575
var centerX;
576576
var centerY;
577577

@@ -638,7 +638,7 @@ describe('@gl Test gl2d plots', function() {
638638
.then(done);
639639
});
640640

641-
it('should change plot type with incomplete data', function(done) {
641+
it('@flaky should change plot type with incomplete data', function(done) {
642642
Plotly.plot(gd, [{}]);
643643
expect(function() {
644644
Plotly.restyle(gd, {type: 'scattergl', x: [[1]]}, 0);
@@ -651,7 +651,7 @@ describe('@gl Test gl2d plots', function() {
651651
done();
652652
});
653653

654-
it('data-referenced annotations should update on drag', function(done) {
654+
it('@flaky data-referenced annotations should update on drag', function(done) {
655655
function assertAnnotation(xy) {
656656
var ann = d3.select('g.annotation-text-g').select('g');
657657
var translate = Drawing.getTranslate(ann);
@@ -694,7 +694,7 @@ describe('@gl Test gl2d plots', function() {
694694
.then(done);
695695
});
696696

697-
it('should not scroll document while panning', function(done) {
697+
it('@flaky should not scroll document while panning', function(done) {
698698
var mock = {
699699
data: [
700700
{ type: 'scattergl', y: [1, 2, 3], x: [1, 2, 3] }
@@ -856,7 +856,7 @@ describe('@gl Test gl2d plots', function() {
856856
.then(done);
857857
});
858858

859-
it('should remove fill2d', function(done) {
859+
it('@flaky should remove fill2d', function(done) {
860860
var mock = require('@mocks/gl2d_axes_labels2.json');
861861

862862
Plotly.plot(gd, mock.data, mock.layout)

0 commit comments

Comments
 (0)