Skip to content

Commit 0b4e549

Browse files
authored
Merge pull request #3706 from plotly/geo-grid-fixes
Geo grid fixes
2 parents 0782274 + 7fce1b3 commit 0b4e549

15 files changed

+237
-81
lines changed

src/plots/geo/geo.js

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ proto.updateBaseLayers = function(fullLayout, geoLayout) {
314314
} else if(isLineLayer(d) || isFillLayer(d)) {
315315
path.datum(topojsonFeature(topojson, topojson.objects[d]));
316316
} else if(isAxisLayer(d)) {
317-
path.datum(makeGraticule(d, geoLayout))
317+
path.datum(makeGraticule(d, geoLayout, fullLayout))
318318
.call(Color.stroke, geoLayout[d].gridcolor)
319319
.call(Drawing.dashLine, '', geoLayout[d].gridwidth);
320320
}
@@ -660,20 +660,58 @@ function getProjection(geoLayout) {
660660
return projection;
661661
}
662662

663-
function makeGraticule(axisName, geoLayout) {
664-
var axisLayout = geoLayout[axisName];
665-
var dtick = axisLayout.dtick;
663+
function makeGraticule(axisName, geoLayout, fullLayout) {
664+
// equivalent to the d3 "ε"
665+
var epsilon = 1e-6;
666+
// same as the geoGraticule default
667+
var precision = 2.5;
668+
669+
var axLayout = geoLayout[axisName];
666670
var scopeDefaults = constants.scopeDefaults[geoLayout.scope];
667-
var lonaxisRange = scopeDefaults.lonaxisRange;
668-
var lataxisRange = scopeDefaults.lataxisRange;
669-
var step = axisName === 'lonaxis' ? [dtick] : [0, dtick];
670-
671-
return d3.geo.graticule()
672-
.extent([
673-
[lonaxisRange[0], lataxisRange[0]],
674-
[lonaxisRange[1], lataxisRange[1]]
675-
])
676-
.step(step);
671+
var rng;
672+
var oppRng;
673+
var coordFn;
674+
675+
if(axisName === 'lonaxis') {
676+
rng = scopeDefaults.lonaxisRange;
677+
oppRng = scopeDefaults.lataxisRange;
678+
coordFn = function(v, l) { return [v, l]; };
679+
} else if(axisName === 'lataxis') {
680+
rng = scopeDefaults.lataxisRange;
681+
oppRng = scopeDefaults.lonaxisRange;
682+
coordFn = function(v, l) { return [l, v]; };
683+
}
684+
685+
var dummyAx = {
686+
type: 'linear',
687+
range: [rng[0], rng[1] - epsilon],
688+
tick0: axLayout.tick0,
689+
dtick: axLayout.dtick
690+
};
691+
692+
Axes.setConvert(dummyAx, fullLayout);
693+
var vals = Axes.calcTicks(dummyAx);
694+
695+
// remove duplicate on antimeridian
696+
if(!geoLayout.isScoped && axisName === 'lonaxis') {
697+
vals.pop();
698+
}
699+
700+
var len = vals.length;
701+
var coords = new Array(len);
702+
703+
for(var i = 0; i < len; i++) {
704+
var v = vals[i].x;
705+
var line = coords[i] = [];
706+
for(var l = oppRng[0]; l < oppRng[1] + precision; l += precision) {
707+
line.push(coordFn(v, l));
708+
}
709+
}
710+
711+
return {
712+
type: 'MultiLineString',
713+
coordinates: coords
714+
};
677715
}
678716

679717
// Returns polygon GeoJSON corresponding to lon/lat range box

src/plots/geo/index.js

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,33 @@
66
* LICENSE file in the root directory of this source tree.
77
*/
88

9-
109
'use strict';
1110

12-
var createGeo = require('./geo');
1311
var getSubplotCalcData = require('../../plots/get_data').getSubplotCalcData;
1412
var counterRegex = require('../../lib').counterRegex;
1513

16-
var GEO = 'geo';
17-
18-
exports.name = GEO;
19-
20-
exports.attr = GEO;
21-
22-
exports.idRoot = GEO;
23-
24-
exports.idRegex = exports.attrRegex = counterRegex(GEO);
25-
26-
exports.attributes = require('./layout/attributes');
27-
28-
exports.layoutAttributes = require('./layout/layout_attributes');
14+
var createGeo = require('./geo');
2915

30-
exports.supplyLayoutDefaults = require('./layout/defaults');
16+
var GEO = 'geo';
17+
var counter = counterRegex(GEO);
18+
19+
var attributes = {};
20+
attributes[GEO] = {
21+
valType: 'subplotid',
22+
role: 'info',
23+
dflt: GEO,
24+
editType: 'calc',
25+
description: [
26+
'Sets a reference between this trace\'s geospatial coordinates and',
27+
'a geographic map.',
28+
'If *geo* (the default value), the geospatial coordinates refer to',
29+
'`layout.geo`.',
30+
'If *geo2*, the geospatial coordinates refer to `layout.geo2`,',
31+
'and so on.'
32+
].join(' ')
33+
};
3134

32-
exports.plot = function plotGeo(gd) {
35+
function plotGeo(gd) {
3336
var fullLayout = gd._fullLayout;
3437
var calcData = gd.calcdata;
3538
var geoIds = fullLayout._subplots[GEO];
@@ -62,9 +65,9 @@ exports.plot = function plotGeo(gd) {
6265

6366
geo.plot(geoCalcData, fullLayout, gd._promises);
6467
}
65-
};
68+
}
6669

67-
exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) {
70+
function clean(newFullData, newFullLayout, oldFullData, oldFullLayout) {
6871
var oldGeoKeys = oldFullLayout._subplots[GEO] || [];
6972

7073
for(var i = 0; i < oldGeoKeys.length; i++) {
@@ -76,9 +79,9 @@ exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout)
7679
oldGeo.clipDef.remove();
7780
}
7881
}
79-
};
82+
}
8083

81-
exports.updateFx = function(gd) {
84+
function updateFx(gd) {
8285
var fullLayout = gd._fullLayout;
8386
var subplotIds = fullLayout._subplots[GEO];
8487

@@ -87,4 +90,18 @@ exports.updateFx = function(gd) {
8790
var subplotObj = subplotLayout._subplot;
8891
subplotObj.updateFx(fullLayout, subplotLayout);
8992
}
93+
}
94+
95+
module.exports = {
96+
attr: GEO,
97+
name: GEO,
98+
idRoot: GEO,
99+
idRegex: counter,
100+
attrRegex: counter,
101+
attributes: attributes,
102+
layoutAttributes: require('./layout_attributes'),
103+
supplyLayoutDefaults: require('./layout_defaults'),
104+
plot: plotGeo,
105+
updateFx: updateFx,
106+
clean: clean
90107
};

src/plots/geo/layout/attributes.js

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/plots/geo/layout/layout_attributes.js renamed to src/plots/geo/layout_attributes.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88

99
'use strict';
1010

11-
var colorAttrs = require('../../../components/color/attributes');
12-
var domainAttrs = require('../../domain').attributes;
13-
var constants = require('../constants');
14-
var overrideAll = require('../../../plot_api/edit_types').overrideAll;
11+
var colorAttrs = require('../../components/color/attributes');
12+
var domainAttrs = require('../domain').attributes;
13+
var constants = require('./constants');
14+
var overrideAll = require('../../plot_api/edit_types').overrideAll;
1515

1616
var geoAxesAttrs = {
1717
range: {
@@ -35,6 +35,7 @@ var geoAxesAttrs = {
3535
tick0: {
3636
valType: 'number',
3737
role: 'info',
38+
dflt: 0,
3839
description: [
3940
'Sets the graticule\'s starting tick longitude/latitude.'
4041
].join(' ')

src/plots/geo/layout/defaults.js renamed to src/plots/geo/layout_defaults.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99

1010
'use strict';
1111

12-
var handleSubplotDefaults = require('../../subplot_defaults');
13-
var constants = require('../constants');
12+
var handleSubplotDefaults = require('../subplot_defaults');
13+
var constants = require('./constants');
1414
var layoutAttributes = require('./layout_attributes');
1515

1616
var axesNames = constants.axesNames;
@@ -58,9 +58,8 @@ function handleGeoDefaults(geoLayoutIn, geoLayoutOut, coerce) {
5858
rangeDflt = [rot - hSpan, rot + hSpan];
5959
}
6060

61-
var range = coerce(axisName + '.range', rangeDflt);
62-
63-
coerce(axisName + '.tick0', range[0]);
61+
coerce(axisName + '.range', rangeDflt);
62+
coerce(axisName + '.tick0');
6463
coerce(axisName + '.dtick', dtickDflt);
6564

6665
show = coerce(axisName + '.showgrid');
7.23 KB
Loading
630 Bytes
Loading
13 Bytes
Loading
-54 Bytes
Loading
10 Bytes
Loading

0 commit comments

Comments
 (0)