Skip to content

Commit a0be087

Browse files
committed
add 'geo.center' + improve defaults & 📚
- `geo.center` was required for persistent map interactions - make `projection.rotation.lon` default value depend on lonaxis range (to get correct view for e.g. #1698) - use lonaxis range OR rotation lon to determine the `geo.center.lon` default - use lataxis range to determine `geo.center.lat` default
1 parent 482cca1 commit a0be087

File tree

3 files changed

+112
-36
lines changed

3 files changed

+112
-36
lines changed

Diff for: src/plots/geo/constants.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ params.scopeDefaults = {
7575
},
7676
europe: {
7777
lonaxisRange: [-30, 60],
78-
lataxisRange: [30, 80],
78+
lataxisRange: [30, 85],
7979
projType: 'conic conformal',
8080
projRotate: [15, 0, 0],
8181
projParallels: [0, 60]

Diff for: src/plots/geo/layout/defaults.js

+73-28
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
var handleSubplotDefaults = require('../../subplot_defaults');
1313
var constants = require('../constants');
1414
var layoutAttributes = require('./layout_attributes');
15-
var supplyGeoAxisLayoutDefaults = require('./axis_defaults');
1615

16+
var axesNames = constants.axesNames;
1717

1818
module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
1919
handleSubplotDefaults(layoutIn, layoutOut, fullData, {
@@ -27,24 +27,64 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
2727
function handleGeoDefaults(geoLayoutIn, geoLayoutOut, coerce) {
2828
var show;
2929

30+
var resolution = coerce('resolution');
3031
var scope = coerce('scope');
31-
var isScoped = (scope !== 'world');
3232
var scopeParams = constants.scopeDefaults[scope];
3333

34-
var resolution = coerce('resolution');
35-
3634
var projType = coerce('projection.type', scopeParams.projType);
37-
var isAlbersUsa = projType === 'albers usa';
38-
var isConic = projType.indexOf('conic') !== -1;
35+
var isAlbersUsa = geoLayoutOut._isAlbersUsa = projType === 'albers usa';
36+
37+
// no other scopes are allowed for 'albers usa' projection
38+
if(isAlbersUsa) scope = geoLayoutOut.scope = 'usa';
39+
40+
var isScoped = geoLayoutOut._isScoped = (scope !== 'world');
41+
var isConic = geoLayoutOut._isConic = projType.indexOf('conic') !== -1;
42+
geoLayoutOut._isClipped = !!constants.lonaxisSpan[projType];
43+
44+
for(var i = 0; i < axesNames.length; i++) {
45+
var axisName = axesNames[i];
46+
var dtickDflt = [30, 10][i];
47+
var rangeDflt;
48+
49+
if(isScoped) {
50+
rangeDflt = scopeParams[axisName + 'Range'];
51+
} else {
52+
var dfltSpans = constants[axisName + 'Span'];
53+
var hSpan = (dfltSpans[projType] || dfltSpans['*']) / 2;
54+
var rot = coerce(
55+
'projection.rotation.' + axisName.substr(0, 3),
56+
scopeParams.projRotate[i]
57+
);
58+
rangeDflt = [rot - hSpan, rot + hSpan];
59+
}
3960

40-
if(isConic) {
41-
var dfltProjParallels = scopeParams.projParallels || [0, 60];
42-
coerce('projection.parallels', dfltProjParallels);
61+
var range = coerce(axisName + '.range', rangeDflt);
62+
63+
coerce(axisName + '.tick0', range[0]);
64+
coerce(axisName + '.dtick', dtickDflt);
65+
66+
show = coerce(axisName + '.showgrid');
67+
if(show) {
68+
coerce(axisName + '.gridcolor');
69+
coerce(axisName + '.gridwidth');
70+
}
4371
}
4472

73+
var lonRange = geoLayoutOut.lonaxis.range;
74+
var latRange = geoLayoutOut.lataxis.range;
75+
76+
// to cross antimeridian w/o ambiguity
77+
var lon0 = lonRange[0];
78+
var lon1 = lonRange[1];
79+
if(lon0 > 0 && lon1 < 0) lon1 += 360;
80+
81+
var centerLon = lon0 + (lon1 - lon0) / 2;
82+
var projLon;
83+
4584
if(!isAlbersUsa) {
46-
var dfltProjRotate = scopeParams.projRotate || [0, 0, 0];
47-
coerce('projection.rotation.lon', dfltProjRotate[0]);
85+
var dfltProjRotate = isScoped ? scopeParams.projRotate : [centerLon, 0, 0];
86+
87+
projLon = coerce('projection.rotation.lon', dfltProjRotate[0]);
4888
coerce('projection.rotation.lat', dfltProjRotate[1]);
4989
coerce('projection.rotation.roll', dfltProjRotate[2]);
5090

@@ -57,7 +97,28 @@ function handleGeoDefaults(geoLayoutIn, geoLayoutOut, coerce) {
5797
show = coerce('showocean');
5898
if(show) coerce('oceancolor');
5999
}
60-
else geoLayoutOut.scope = 'usa';
100+
101+
var centerLonDflt;
102+
var centerLatDflt;
103+
104+
if(isAlbersUsa) {
105+
// 'albers usa' does not have a 'center',
106+
// these values were found using via:
107+
// projection.invert([geoLayout.center.lon, geoLayoutIn.center.lat])
108+
centerLonDflt = -96.6;
109+
centerLatDflt = 38.7;
110+
} else {
111+
centerLonDflt = isScoped ? centerLon : projLon;
112+
centerLatDflt = latRange[0] + (latRange[1] - latRange[0]) / 2;
113+
}
114+
115+
coerce('center.lon', centerLonDflt);
116+
coerce('center.lat', centerLatDflt);
117+
118+
if(isConic) {
119+
var dfltProjParallels = scopeParams.projParallels || [0, 60];
120+
coerce('projection.parallels', dfltProjParallels);
121+
}
61122

62123
coerce('projection.scale');
63124

@@ -98,20 +159,4 @@ function handleGeoDefaults(geoLayoutIn, geoLayoutOut, coerce) {
98159
}
99160

100161
coerce('bgcolor');
101-
102-
supplyGeoAxisLayoutDefaults(geoLayoutIn, geoLayoutOut);
103-
104-
// bind a few helper variables
105-
geoLayoutOut._isHighRes = resolution === 50;
106-
geoLayoutOut._clipAngle = constants.lonaxisSpan[projType] / 2;
107-
geoLayoutOut._isAlbersUsa = isAlbersUsa;
108-
geoLayoutOut._isConic = isConic;
109-
geoLayoutOut._isScoped = isScoped;
110-
111-
var rotation = geoLayoutOut.projection.rotation || {};
112-
geoLayoutOut.projection._rotate = [
113-
-rotation.lon || 0,
114-
-rotation.lat || 0,
115-
rotation.roll || 0
116-
];
117162
}

Diff for: src/plots/geo/layout/layout_attributes.js

+38-7
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ var geoAxesAttrs = {
2222
],
2323
description: [
2424
'Sets the range of this axis (in degrees),',
25+
'sets the map\'s clipped coordinates.'
2526
].join(' ')
2627
},
2728
showgrid: {
@@ -74,8 +75,11 @@ module.exports = overrideAll({
7475
],
7576
dflt: [0, 1],
7677
description: [
77-
'Sets the horizontal domain of this map',
78-
'(in plot fraction).'
78+
'Sets the maximum horizontal domain of this map',
79+
'(in plot fraction).',
80+
'Note that geo subplots are constrained by domain.',
81+
'In general, when `projection.scale` is set to 1.',
82+
'a map will fit either its x or y domain, but not both. '
7983
].join(' ')
8084
},
8185
y: {
@@ -87,8 +91,11 @@ module.exports = overrideAll({
8791
],
8892
dflt: [0, 1],
8993
description: [
90-
'Sets the vertical domain of this map',
91-
'(in plot fraction).'
94+
'Sets the maximum vertical domain of this map',
95+
'(in plot fraction).',
96+
'Note that geo subplots are constrained by domain.',
97+
'In general, when `projection.scale` is set to 1.',
98+
'a map will fit either its x or y domain, but not both. '
9299
].join(' ')
93100
}
94101
},
@@ -124,7 +131,8 @@ module.exports = overrideAll({
124131
role: 'info',
125132
description: [
126133
'Rotates the map along parallels',
127-
'(in degrees East).'
134+
'(in degrees East).',
135+
'Defaults to the center of the `lonaxis.range` values.'
128136
].join(' ')
129137
},
130138
lat: {
@@ -161,9 +169,32 @@ module.exports = overrideAll({
161169
valType: 'number',
162170
role: 'info',
163171
min: 0,
164-
max: 10,
165172
dflt: 1,
166-
description: 'Zooms in or out on the map view.'
173+
description: [
174+
'Zooms in or out on the map view.',
175+
'A scale of *1* corresponds to the largest zoom level',
176+
'that fits the map\'s lon and lat ranges. '
177+
].join(' ')
178+
},
179+
},
180+
center: {
181+
lon: {
182+
valType: 'number',
183+
role: 'info',
184+
description: [
185+
'Sets the longitude of the map\'s center.',
186+
'By default, the map\'s longitude center lies at the middle of the longitude range',
187+
'for scoped projection and above `projection.rotation.lon` otherwise.'
188+
].join(' ')
189+
},
190+
lat: {
191+
valType: 'number',
192+
role: 'info',
193+
description: [
194+
'Sets the latitude of the map\'s center.',
195+
'For all projection types, the map\'s latitude center lies',
196+
'at the middle of the latitude range by default.'
197+
].join(' ')
167198
}
168199
},
169200
showcoastlines: {

0 commit comments

Comments
 (0)