Skip to content

Commit bfe0211

Browse files
committed
make scattergeo calcdata 1-1 with lon/lat items in fullData
- use BADNUM to normalize non-numeric lon/lat handling - and instead remove BADNUM pts in plot step - this is consistent with all other d3 plot type (!!) - allows us to reuse scatter/arrays_to_calcdata - and cleans up locations -> lonlat logic!
1 parent caade64 commit bfe0211

File tree

3 files changed

+48
-91
lines changed

3 files changed

+48
-91
lines changed

src/traces/scattergeo/calc.js

+13-24
Original file line numberDiff line numberDiff line change
@@ -10,45 +10,34 @@
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];
30-
31-
calcPt.loc = loc;
32-
skip = (typeof loc !== 'string');
28+
calcPt.loc = typeof loc === 'string' ? loc : null;
3329
}
3430
else {
35-
var lon = trace.lon[i],
36-
lat = trace.lat[i];
31+
var lon = trace.lon[i];
32+
var lat = trace.lat[i];
33+
calcPt.lonlat = new Array(2);
3734

38-
calcPt.lonlat = [+lon, +lat];
39-
skip = (!isNumeric(lon) || !isNumeric(lat));
35+
calcPt.lonlat[0] = isNumeric(lon) ? +lon : BADNUM;
36+
calcPt.lonlat[1] = isNumeric(lat) ? +lat : BADNUM;
4037
}
41-
42-
if(skip) {
43-
if(cnt > 0) calcTrace[cnt - 1].gapAfter = true;
44-
continue;
45-
}
46-
47-
cnt++;
48-
49-
calcTrace.push(calcPt);
5038
}
5139

40+
arraysToCalcdata(calcTrace, trace);
5241
calcMarkerColorscale(trace);
5342

5443
return calcTrace;

src/traces/scattergeo/hover.js

+2-2
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');
@@ -32,8 +33,7 @@ module.exports = function hoverPoints(pointData) {
3233
function distFn(d) {
3334
var lonlat = d.lonlat;
3435

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

3838
if(geo.isLonLatOverEdges(lonlat)) return Infinity;
3939

src/traces/scattergeo/plot.js

+33-65
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,28 @@ 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+
var lonlat = d.lonlat;
31+
if(lonlat[0] === BADNUM || lonlat[1] === BADNUM) {
32+
d3.select(node).remove();
33+
}
34+
}
35+
36+
for(var i = 0; i < calcData.length; i++) {
37+
fillLocationLonLat(calcData[i], geo.topojson);
38+
}
39+
2940
var gScatterGeoTraces = geo.framework.select('.scattergeolayer')
3041
.selectAll('g.trace.scattergeo')
3142
.data(calcData, keyFunc);
@@ -39,27 +50,11 @@ module.exports = function plot(geo, calcData) {
3950
gScatterGeoTraces.selectAll('*').remove();
4051

4152
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-
}
53+
var s = d3.select(this);
54+
var trace = calcTrace[0].trace;
6055

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

6459
var lineData = (trace.fill !== 'none') ?
6560
geoJsonUtils.makePolygon(lineCoords, trace) :
@@ -72,66 +67,39 @@ module.exports = function plot(geo, calcData) {
7267
}
7368

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

8077
if(subTypes.hasText(trace)) {
81-
s.selectAll('g').data(_calcTrace)
78+
s.selectAll('g')
79+
.data(Lib.identity)
8280
.enter().append('g')
83-
.append('text');
81+
.append('text')
82+
.each(function(calcPt) { removeBADNUM(calcPt, this); });
8483
}
8584
});
8685

8786
// call style here within topojson request callback
8887
style(geo);
8988
};
9089

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;
90+
function fillLocationLonLat(calcTrace, topojson) {
91+
var trace = calcTrace[0].trace;
9692

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

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-
}
95+
var features = getTopojsonFeatures(trace, topojson);
96+
var locationmode = trace.locationmode;
11197

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-
}
98+
for(var i = 0; i < calcTrace.length; i++) {
99+
var calcPt = calcTrace[i];
100+
var feature = locationToFeature(locationmode, calcPt.loc, features);
126101

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');
102+
calcPt.lonlat = feature ? feature.properties.ct : [BADNUM, BADNUM];
135103
}
136104
}
137105

0 commit comments

Comments
 (0)