8000 Geo refactor and lasso/select-box selections by etpinard · Pull Request #2030 · plotly/plotly.js · GitHub
[go: up one dir, main page]

Skip to content

Geo refactor and lasso/select-box selections #2030

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 42 commits into from
Sep 28, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
4c1ddb8
Introduce geo 2.0
etpinard Sep 21, 2017
482cca1
merge geo axis attrs module into 'main' layout attr module
etpinard Sep 21, 2017
a0be087
add 'geo.center' + improve defaults & :books:
etpinard Sep 21, 2017
e9efdd0
use relayout in geo modeBar buttons
etpinard Sep 21, 2017
9faa1b1
sync pan/scroll interactions into user/full layout
etpinard Sep 21, 2017
d0ea7c9
adapt scattergeo to new geo layers and projection logic
etpinard Sep 21, 2017
a981eb5
adapt choropleth plot and hover (in preparation for selections)
etpinard Sep 21, 2017
44f56dd
prelim stuff for geo selections
etpinard Sep 21, 2017
e53a908
DRY up select test suite
etpinard Sep 21, 2017
0e22ba0
add scattergeo lasso/select
etpinard Sep 21, 2017
397d47c
add choropleth lasso/select
etpinard Sep 21, 2017
825e24d
resolves #1995 - add a miter limit on scattergeo
etpinard Sep 21, 2017
24c2422
clean up and improve geo defaults tests
etpinard Sep 21, 2017
c2b0f9c
resolves #292 - add mucho test for geo pan/scroll interactions
etpinard Sep 21, 2017
3bd89d3
add one geo base layer update test
etpinard Sep 21, 2017
e59c90b
resolves #1698 - add geo_across-antimeridian mock
etpinard Sep 21, 2017
eaf44a8
resolves #1996 - add `geo_scattergeo-out-of-usa`
etpinard Sep 21, 2017
4d9b566
resolves #1486 - add `geo_centering` mock
etpinard Sep 21, 2017
32a29c7
update conic baselines
etpinard Sep 21, 2017
be59f69
update a few scoped baseline
etpinard Sep 21, 2017
36833d4
update `geo_fill` mock
etpinard Sep 22, 2017
7e5bb41
update baseline to show proper marker.opacity
etpinard Sep 22, 2017
a30beea
update other geo baselines
etpinard Sep 22, 2017
fd5bf11
:hocho: obsolete files and logic
etpinard Sep 22, 2017
ae48369
rename temporary geo2.js -> geo.js :tada:
etpinard Sep 22, 2017
5bc2c71
add 'step' name to failure message
etpinard Sep 25, 2017
ab05990
compute geo.midPt more efficiently
etpinard Sep 25, 2017
ce31666
lint (rename params -> exports)
etpinard Sep 25, 2017
eeee911
use {} instead of [] to identify line & fill layers
etpinard Sep 25, 2017
71c5355
improve selection queries
etpinard Sep 25, 2017
a3df09e
use beforeEach in per-trace select tests
etpinard Sep 25, 2017
05e8194
update across antimeridian mock
etpinard Sep 25, 2017
935e4ac
add jasmine test
etpinard Sep 25, 2017
2488f4b
add per-basePlot-module updateFx methods
etpinard Sep 25, 2017
303de22
add `stroke-miterlimit: 2` to base layer lines
etpinard Sep 25, 2017
9bb7d91
use dragElement.unhover to queued Fx.hover calls
etpinard Sep 26, 2017
1c26ec4
add geo.project and use that in scattergeo hover
etpinard Sep 26, 2017
1d2ce2d
handle invalid geo setting that lead to invalid bounds
etpinard Sep 26, 2017
651399e
fix choropleth hover for countries w/ have polygons that cross -180
etpinard Sep 27, 2017
8f9b75a
add _clips and _topclips <g> in makePlotFramework
etpinard Sep 27, 2017
0089488
lint
etpinard Sep 27, 2017
190c733
fix choropleth hover over Antarctica
etpinard Sep 27, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix choropleth hover for countries w/ have polygons that cross -180
- these countries are Russia and Fiji.
- Note that other countries have polygons on either side of
  the antimeridian (e.g. some Aleutian island for the USA),
  but those don't confuse the 'contains' method.
  • Loading branch information
etpinard committed Sep 27, 2017
commit 651399e430dfdff6f91b3c06cebeba07898d82b7
4 changes: 4 additions & 0 deletions src/traces/choropleth/hover.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ module.exports = function hoverPoints(pointData, xval, yval) {
if(pt._polygons[j].contains([xval, yval])) {
isInside = !isInside;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to have a record of it - @etpinard and I discussed this in chat: in principle it would be faster to keep the nesting structure of the geojson, that tells us the difference between exterior and internal polygons. Then we could:

  • Look for the first exterior loop we are inside
  • Don’t check any more exterior loops after that
  • Only check the interior loops for that particular exterior loop

But for now there can only be at most 200 locations, for ~ 200 countries, and polygon.contains should short-circuit most of these based on their bounding boxes, so this is not a big deal. If we ever add US counties or something we can revisit. But then @etpinard points out that this becomes complicated in a few obnoxious cases of higher-order nesting which this simple but slower algorithm (are you inside an odd number of polygons?) gets right.

10000
}
// for polygons that cross antimeridian as xval is in [-180, 180]
if(pt._polygons[j].contains([xval + 360, yval])) {
isInside = !isInside;
}
}

if(isInside) break;
Expand Down
21 changes: 20 additions & 1 deletion src/traces/choropleth/plot.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ function calcGeoJSON(calcTrace, topojson) {
var trace = calcTrace[0].trace;
var len = calcTrace.length;
var features = getTopojsonFeatures(trace, topojson);
var i, j, k;
var i, j, k, m;

for(i = 0; i < len; i++) {
var calcPt = calcTrace[i];
Expand All @@ -74,6 +74,25 @@ function calcGeoJSON(calcTrace, topojson) {
var coords = geometry.coordinates;
calcPt._polygons = [];

// Russia and Fiji have landmasses that cross the antimeridian,
// we need to add +360 to their longitude coordinates, so that
// polygon 'contains' doesn't get confused when crossing the antimeridian.
//
// Note that other countries have polygons on either side of the antimeridian
// (e.g. some Aleutian island for the USA), but those don't confuse
// the 'contains' method; these are skipped here.
if(calcPt.loc === 'RUS' || calcPt.loc === 'FJI') {
for(j = 0; j < coords.length; j++) {
for(k = 0; k < coords[j].length; k++) {
for(m = 0; m < coords[j][k].length; m++) {
if(coords[j][k][m][0] < 0) {
coords[j][k][m][0] += 360;
}
}
}
}
}

switch(geometry.type) {
case 'MultiPolygon':
for(j = 0; j < coords.length; j++) {
Expand Down
40 changes: 40 additions & 0 deletions test/jasmine/tests/geo_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1290,6 +1290,46 @@ describe('Test geo interactions', function() {
.catch(fail)
.then(done);
});

it('should get hover right for choropleths involving landmasses that cross antimeridian', function(done) {
var gd = createGraphDiv();

function check(lonlat, hoverLabelCnt, msg) {
var projection = gd._fullLayout.geo._subplot.projection;
var px = projection(lonlat);

mouseEvent('mousemove', px[0], px[1]);
expect(d3.selectAll('g.hovertext').size()).toBe(hoverLabelCnt, msg);

delete gd._lastHoverTime;
}

Plotly.newPlot(gd, [{
type: 'choropleth',
locations: ['RUS', 'FJI'],
z: [0, 1]
}])
.then(function() {
check([81, 66], 1, 'spot in north-central Russia that polygon.contains gets wrong before +360 shift');
check([-80, 66], 0, 'spot north of Hudson bay that polygon.contains believe is in Russia before before +360 shift');

return Plotly.relayout(gd, 'geo.projection.rotation.lon', 180);
})
.then(function() {
check([-174, 65], 1, 'spot in Russia mainland beyond antimeridian');

return Plotly.relayout(gd, {
'geo.center.lat': -16,
'geo.projection.scale': 17
});
})
.then(function() {
check([179, -16.6], 1, 'spot on Fiji island that cross antimeridian west of antimeridian');
check([-179.9, -16.2], 1, 'spot on Fiji island that cross antimeridian east of antimeridian');
})
.catch(fail)
.then(done);
});
});

describe('Test event property of interactions on a geo plot:', function() {
Expand Down
0