Skip to content

Commit 0ec992e

Browse files
authored
Merge pull request #1538 from plotly/scattergeo-badnum
Scattergeo BADNUM
2 parents 10acee0 + 248b760 commit 0ec992e

19 files changed

+320
-419
lines changed

src/lib/geojson_utils.js

+10-7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
'use strict';
1111

12+
var BADNUM = require('../constants/numerical').BADNUM;
13+
1214
/**
1315
* Convert calcTrace to GeoJSON 'MultiLineString' coordinate arrays
1416
*
@@ -21,18 +23,19 @@
2123
*
2224
*/
2325
exports.calcTraceToLineCoords = function(calcTrace) {
24-
var trace = calcTrace[0].trace,
25-
connectgaps = trace.connectgaps;
26+
var trace = calcTrace[0].trace;
27+
var connectgaps = trace.connectgaps;
2628

27-
var coords = [],
28-
lineString = [];
29+
var coords = [];
30+
var lineString = [];
2931

3032
for(var i = 0; i < calcTrace.length; i++) {
3133
var calcPt = calcTrace[i];
34+
var lonlat = calcPt.lonlat;
3235

33-
lineString.push(calcPt.lonlat);
34-
35-
if(!connectgaps && calcPt.gapAfter && lineString.length > 0) {
36+
if(lonlat[0] !== BADNUM) {
37+
lineString.push(lonlat);
38+
} else if(!connectgaps && lineString.length > 0) {
3639
coords.push(lineString);
3740
lineString = [];
3841
}

src/plots/mapbox/mapbox.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,14 @@ proto.createMap = function(calcData, fullLayout, resolve, reject) {
111111
});
112112

113113
// clear navigation container
114-
var className = constants.controlContainerClassName,
115-
controlContainer = self.div.getElementsByClassName(className)[0];
114+
var className = constants.controlContainerClassName;
115+
var controlContainer = self.div.getElementsByClassName(className)[0];
116116
self.div.removeChild(controlContainer);
117117

118+
// make sure canvas does not inherit left and top css
119+
map._canvas.canvas.style.left = '0px';
120+
map._canvas.canvas.style.top = '0px';
121+
118122
self.rejectOnError(reject);
119123

120124
map.once('load', function() {
@@ -176,7 +180,6 @@ proto.createMap = function(calcData, fullLayout, resolve, reject) {
176180

177181
map.on('dragstart', unhover);
178182
map.on('zoomstart', unhover);
179-
180183
};
181184

182185
proto.updateMap = function(calcData, fullLayout, resolve, reject) {

src/plots/plots.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ var Plotly = require('../plotly');
1616
var Registry = require('../registry');
1717
var Lib = require('../lib');
1818
var Color = require('../components/color');
19+
var BADNUM = require('../constants/numerical').BADNUM;
1920

2021
var plots = module.exports = {};
2122

@@ -2015,11 +2016,8 @@ plots.doCalcdata = function(gd, traces) {
20152016
//
20162017
// This ensures there is a calcdata item for every trace,
20172018
// even if cartesian logic doesn't handle it (for things like legends).
2018-
//
2019-
// Tag this artificial calc point with 'placeholder: true',
2020-
// to make it easier to skip over them in during the plot and hover step.
20212019
if(!Array.isArray(cd) || !cd[0]) {
2022-
cd = [{x: false, y: false, placeholder: true}];
2020+
cd = [{x: BADNUM, y: BADNUM}];
20232021
}
20242022

20252023
// add the trace-wide properties to the first point,

src/traces/scattergeo/calc.js

+13-26
Original file line numberDiff line numberDiff line change
@@ -10,45 +10,32 @@
1010
'use strict';
1111

1212
var isNumeric = require('fast-isnumeric');
13+
var BADNUM = require('../../constants/numerical').BADNUM;
1314

1415
var calcMarkerColorscale = require('../scatter/colorscale_calc');
15-
16+
var arraysToCalcdata = require('../scatter/arrays_to_calcdata');
1617

1718
module.exports = function calc(gd, trace) {
18-
var hasLocationData = Array.isArray(trace.locations),
19-
len = hasLocationData ? trace.locations.length : trace.lon.length;
20-
21-
var calcTrace = [],
22-
cnt = 0;
19+
var hasLocationData = Array.isArray(trace.locations);
20+
var len = hasLocationData ? trace.locations.length : trace.lon.length;
21+
var calcTrace = new Array(len);
2322

2423
for(var i = 0; i < len; i++) {
25-
var calcPt = {},
26-
skip;
24+
var calcPt = calcTrace[i] = {};
2725

2826
if(hasLocationData) {
2927
var loc = trace.locations[i];
28+
calcPt.loc = typeof loc === 'string' ? loc : null;
29+
} else {
30+
var lon = trace.lon[i];
31+
var lat = trace.lat[i];
3032

31-
calcPt.loc = loc;
32-
skip = (typeof loc !== 'string');
33-
}
34-
else {
35-
var lon = trace.lon[i],
36-
lat = trace.lat[i];
37-
38-
calcPt.lonlat = [+lon, +lat];
39-
skip = (!isNumeric(lon) || !isNumeric(lat));
33+
if(isNumeric(lon) && isNumeric(lat)) calcPt.lonlat = [+lon, +lat];
34+
else calcPt.lonlat = [BADNUM, BADNUM];
4035
}
41-
42-
if(skip) {
43-
if(cnt > 0) calcTrace[cnt - 1].gapAfter = true;
44-
continue;
45-
}
46-
47-
cnt++;
48-
49-
calcTrace.push(calcPt);
5036
}
5137

38+
arraysToCalcdata(calcTrace, trace);
5239
calcMarkerColorscale(trace);
5340

5441
return calcTrace;

src/traces/scattergeo/hover.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
var Fx = require('../../plots/cartesian/graph_interact');
1313
var Axes = require('../../plots/cartesian/axes');
14+
var BADNUM = require('../../constants/numerical').BADNUM;
1415

1516
var getTraceColor = require('../scatter/get_trace_color');
1617
var attributes = require('./attributes');
@@ -23,17 +24,14 @@ module.exports = function hoverPoints(pointData) {
2324
ya = pointData.ya,
2425
geo = pointData.subplot;
2526

26-
if(cd[0].placeholder) return;
27-
2827
function c2p(lonlat) {
2928
return geo.projection(lonlat);
3029
}
3130

3231
function distFn(d) {
3332
var lonlat = d.lonlat;
3433

35-
// this handles the not-found location feature case
36-
if(lonlat[0] === null || lonlat[1] === null) return Infinity;
34+
if(lonlat[0] === BADNUM) return Infinity;
3735

3836
if(geo.isLonLatOverEdges(lonlat)) return Infinity;
3937

src/traces/scattergeo/plot.js

+32-65
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,27 @@ var Drawing = require('../../components/drawing');
1515
var Color = require('../../components/color');
1616

1717
var Lib = require('../../lib');
18+
var BADNUM = require('../../constants/numerical').BADNUM;
1819
var getTopojsonFeatures = require('../../lib/topojson_utils').getTopojsonFeatures;
1920
var locationToFeature = require('../../lib/geo_location_utils').locationToFeature;
2021
var geoJsonUtils = require('../../lib/geojson_utils');
21-
var arrayToCalcItem = require('../../lib/array_to_calc_item');
2222
var subTypes = require('../scatter/subtypes');
2323

2424

2525
module.exports = function plot(geo, calcData) {
2626

2727
function keyFunc(d) { return d[0].trace.uid; }
2828

29+
function removeBADNUM(d, node) {
30+
if(d.lonlat[0] === BADNUM) {
31+
d3.select(node).remove();
32+
}
33+
}
34+
35+
for(var i = 0; i < calcData.length; i++) {
36+
fillLocationLonLat(calcData[i], geo.topojson);
37+
}
38+
2939
var gScatterGeoTraces = geo.framework.select('.scattergeolayer')
3040
.selectAll('g.trace.scattergeo')
3141
.data(calcData, keyFunc);
@@ -39,27 +49,11 @@ module.exports = function plot(geo, calcData) {
3949
gScatterGeoTraces.selectAll('*').remove();
4050

4151
gScatterGeoTraces.each(function(calcTrace) {
42-
var s = d3.select(this),
43-
trace = calcTrace[0].trace,
44-
convertToLonLatFn = makeConvertToLonLatFn(trace, geo.topojson);
45-
46-
// skip over placeholder traces
47-
if(calcTrace[0].placeholder) s.remove();
48-
49-
// just like calcTrace but w/o not-found location datum
50-
var _calcTrace = [];
51-
52-
for(var i = 0; i < calcTrace.length; i++) {
53-
var _calcPt = convertToLonLatFn(calcTrace[i]);
54-
55-
if(_calcPt) {
56-
arrayItemToCalcdata(trace, calcTrace[i], i);
57-
_calcTrace.push(_calcPt);
58-
}
59-
}
52+
var s = d3.select(this);
53+
var trace = calcTrace[0].trace;
6054

6155
if(subTypes.hasLines(trace) || trace.fill !== 'none') {
62-
var lineCoords = geoJsonUtils.calcTraceToLineCoords(_calcTrace);
56+
var lineCoords = geoJsonUtils.calcTraceToLineCoords(calcTrace);
6357

6458
var lineData = (trace.fill !== 'none') ?
6559
geoJsonUtils.makePolygon(lineCoords, trace) :
@@ -72,66 +66,39 @@ module.exports = function plot(geo, calcData) {
7266
}
7367

7468
if(subTypes.hasMarkers(trace)) {
75-
s.selectAll('path.point').data(_calcTrace)
76-
.enter().append('path')
77-
.classed('point', true);
69+
s.selectAll('path.point')
70+
.data(Lib.identity)
71+
.enter().append('path')
72+
.classed('point', true)
73+
.each(function(calcPt) { removeBADNUM(calcPt, this); });
7874
}
7975

8076
if(subTypes.hasText(trace)) {
81-
s.selectAll('g').data(_calcTrace)
77+
s.selectAll('g')
78+
.data(Lib.identity)
8279
.enter().append('g')
83-
.append('text');
80+
.append('text')
81+
.each(function(calcPt) { removeBADNUM(calcPt, this); });
8482
}
8583
});
8684

8785
// call style here within topojson request callback
8886
style(geo);
8987
};
9088

91-
function makeConvertToLonLatFn(trace, topojson) {
92-
if(!Array.isArray(trace.locations)) return Lib.identity;
93-
94-
var features = getTopojsonFeatures(trace, topojson),
95-
locationmode = trace.locationmode;
89+
function fillLocationLonLat(calcTrace, topojson) {
90+
var trace = calcTrace[0].trace;
9691

97-
return function(calcPt) {
98-
var feature = locationToFeature(locationmode, calcPt.loc, features);
92+
if(!Array.isArray(trace.locations)) return;
9993

100-
if(feature) {
101-
calcPt.lonlat = feature.properties.ct;
102-
return calcPt;
103-
}
104-
else {
105-
// mutate gd.calcdata so that hoverPoints knows to skip this datum
106-
calcPt.lonlat = [null, null];
107-
return false;
108-
}
109-
};
110-
}
94+
var features = getTopojsonFeatures(trace, topojson);
95+
var locationmode = trace.locationmode;
11196

112-
function arrayItemToCalcdata(trace, calcItem, i) {
113-
var marker = trace.marker;
114-
115-
function merge(traceAttr, calcAttr) {
116-
arrayToCalcItem(traceAttr, calcItem, calcAttr, i);
117-
}
118-
119-
merge(trace.text, 'tx');
120-
merge(trace.textposition, 'tp');
121-
if(trace.textfont) {
122-
merge(trace.textfont.size, 'ts');
123-
merge(trace.textfont.color, 'tc');
124-
merge(trace.textfont.family, 'tf');
125-
}
97+
for(var i = 0; i < calcTrace.length; i++) {
98+
var calcPt = calcTrace[i];
99+
var feature = locationToFeature(locationmode, calcPt.loc, features);
126100

127-
if(marker && marker.line) {
128-
var markerLine = marker.line;
129-
merge(marker.opacity, 'mo');
130-
merge(marker.symbol, 'mx');
131-
merge(marker.color, 'mc');
132-
merge(marker.size, 'ms');
133-
merge(markerLine.color, 'mlc');
134-
merge(markerLine.width, 'mlw');
101+
calcPt.lonlat = feature ? feature.properties.ct : [BADNUM, BADNUM];
135102
}
136103
}
137104

0 commit comments

Comments
 (0)