Skip to content

Commit 4eed12e

Browse files
committed
Fix scattermap selection across antimeridian
1 parent 437cb2b commit 4eed12e

2 files changed

Lines changed: 90 additions & 1 deletion

File tree

src/plots/map/map.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,15 @@ proto.addLayer = function(opts, below) {
727727

728728
// convenience method to project a [lon, lat] array to pixel coords
729729
proto.project = function(v) {
730-
return this.map.project(new maplibregl.LngLat(v[0], v[1]));
730+
var map = this.map;
731+
var lon = v[0];
732+
733+
if(map.getRenderWorldCopies()) {
734+
var centerLon = map.getCenter().lng;
735+
lon = centerLon + Lib.modHalf(lon - centerLon, 360);
736+
}
737+
738+
return map.project(new maplibregl.LngLat(lon, v[1]));
731739
};
732740

733741
// get map's current view values in plotly.js notation

test/jasmine/tests/select_test.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2276,6 +2276,87 @@ describe('Test select box and lasso per trace:', function() {
22762276
}, LONG_TIMEOUT_INTERVAL);
22772277
});
22782278

2279+
it('@gl should select scattermap points across the antimeridian', function(done) {
2280+
var lons = [174.76, 178.44, 179.9, -176.2, -171.77, -175.2];
2281+
var lats = [-36.85, -18.14, -16.5, -13.3, -13.83, -21.14];
2282+
var expectedPoints = lons.map(function(lon, i) { return [lon, lats[i]]; });
2283+
var assertPoints = makeAssertPoints(['lon', 'lat']);
2284+
var assertSelectedPoints = makeAssertSelectedPoints();
2285+
var boxPath;
2286+
var lassoPath;
2287+
2288+
var fig = {
2289+
data: [{
2290+
type: 'scattermap',
2291+
mode: 'markers',
2292+
lon: lons,
2293+
lat: lats,
2294+
marker: {size: 10}
2295+
}],
2296+
layout: {
2297+
dragmode: 'select',
2298+
width: 900,
2299+
height: 600,
2300+
map: {
2301+
center: {lon: 180, lat: -24},
2302+
style: 'white-bg',
2303+
zoom: 3
2304+
}
2305+
},
2306+
config: {}
2307+
};
2308+
2309+
_newPlot(gd, fig)
2310+
.then(function() {
2311+
var subplot = gd._fullLayout.map._subplot;
2312+
var points = lons.map(function(lon, i) {
2313+
var unwrappedLon = lon < 0 ? lon + 360 : lon;
2314+
var pt = subplot.map.project([unwrappedLon, lats[i]]);
2315+
return [pt.x + subplot.xaxis._offset, pt.y + subplot.yaxis._offset];
2316+
});
2317+
var xs = points.map(function(pt) { return pt[0]; });
2318+
var ys = points.map(function(pt) { return pt[1]; });
2319+
var x0 = Math.min.apply(null, xs) - 10;
2320+
var x1 = Math.max.apply(null, xs) + 10;
2321+
var y0 = Math.min.apply(null, ys) - 10;
2322+
var y1 = Math.max.apply(null, ys) + 10;
2323+
2324+
boxPath = [[x0, y0], [x1, y1]];
2325+
lassoPath = [[x0, y0], [x0, y1], [x1, y1], [x1, y0], [x0, y0]];
2326+
2327+
return _run(false, boxPath,
2328+
function() {
2329+
assertPoints(expectedPoints);
2330+
assertSelectedPoints({0: [0, 1, 2, 3, 4, 5]});
2331+
2332+
var range = selectedData.range.map;
2333+
expect(range[1][0]).toBeGreaterThan(range[0][0], 'continuous longitude range');
2334+
expect(range[1][0]).toBeGreaterThan(180, 'east edge is unwrapped past 180');
2335+
},
2336+
null, BOXEVENTS, 'scattermap antimeridian select'
2337+
);
2338+
})
2339+
.then(function() {
2340+
return Plotly.relayout(gd, 'dragmode', 'lasso');
2341+
})
2342+
.then(function() {
2343+
return _run(false, lassoPath,
2344+
function() {
2345+
assertPoints(expectedPoints);
2346+
assertSelectedPoints({0: [0, 1, 2, 3, 4, 5]});
2347+
2348+
var lassoPoints = selectedData.lassoPoints.map;
2349+
for(var i = 1; i < lassoPoints.length; i++) {
2350+
expect(Math.abs(lassoPoints[i][0] - lassoPoints[i - 1][0]))
2351+
.toBeLessThan(180, 'continuous lasso longitude');
2352+
}
2353+
},
2354+
null, LASSOEVENTS, 'scattermap antimeridian lasso'
2355+
);
2356+
})
2357+
.then(done, done.fail);
2358+
}, LONG_TIMEOUT_INTERVAL);
2359+
22792360
[false, true].forEach(function(hasCssTransform) {
22802361
it('@gl should work on choroplethmap traces, hasCssTransform: ' + hasCssTransform, function(done) {
22812362
var assertPoints = makeAssertPoints(['location', 'z']);

0 commit comments

Comments
 (0)