Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test adding an option to use country borderlines from a UN geojson dataset for geo subplots #7327

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
7 changes: 3 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -112,6 +112,7 @@
"regl-line2d": "^3.1.3",
"regl-scatter2d": "^3.3.1",
"regl-splom": "^1.0.14",
"sane-topojson": "github:etpinard/sane-topojson#c76e75396879a1a8d96e37237383b3ca5305afc6",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"strongly-connected-components": "^1.0.1",
"style-loader": "^4.0.0",
"superscript-text": "^1.0.0",
@@ -172,7 +173,6 @@
"raw-loader": "^4.0.2",
"read-last-lines": "^1.8.0",
"run-series": "^1.1.9",
"sane-topojson": "^4.0.0",
"sass": "^1.78.0",
"stream-browserify": "^3.0.0",
"through2": "^4.0.2",
1 change: 1 addition & 0 deletions src/components/drawing/index.js
Original file line number Diff line number Diff line change
@@ -1775,6 +1775,7 @@ function getMarkerAngle(d, trace) {
}

if(trace._geo) {
if(!d.latlon) return null;
var lon = d.lonlat[0];
var lat = d.lonlat[1];

66 changes: 64 additions & 2 deletions src/lib/geo_location_utils.js
Original file line number Diff line number Diff line change
@@ -41,6 +41,8 @@ function locationToFeature(locationmode, location, features) {
var filteredFeatures;
var f, i;

var allParts = [];

if(locationId) {
if(locationmode === 'USA-states') {
// Filter out features out in USA
@@ -63,6 +65,12 @@ function locationToFeature(locationmode, location, features) {
for(i = 0; i < filteredFeatures.length; i++) {
f = filteredFeatures[i];
if(f.id === locationId) return f;
if(
f.properties &&
f.properties.iso3cd === locationId
) {
allParts.push(f);
}
}

loggers.log([
@@ -71,13 +79,38 @@ function locationToFeature(locationmode, location, features) {
].join(' '));
}

if(allParts.length) {
return allParts; //[allParts.length - 1];
}

return false;
}

function feature2polygons(feature) {
if(!Array.isArray(feature)) {
return _feature2polygons(feature);
}

var polygons;
for(var i = 0; i < feature.length; i++) {
var pts = _feature2polygons(feature[i]);

if(pts.length) {
if(!polygons) {
polygons = pts;
} else {
polygons.push(polygon.tester(pts));
}
}
}

return polygons;
}

function _feature2polygons(feature) {
var geometry = feature.geometry;
var coords = geometry.coordinates;
var loc = feature.id;
var loc = feature.properties.iso3cd || feature.id;

var polygons = [];
var appendPolygon, j, k, m;
@@ -173,6 +206,9 @@ function feature2polygons(feature) {
appendPolygon(coords[j]);
}
break;
case 'LineString':
appendPolygon(coords);
break;
}

return polygons;
@@ -363,9 +399,35 @@ function fetchTraceGeoData(calcData) {
return promises;
}


function computeBbox(d) {
if(!Array.isArray(d)) {
return _computeBbox(d);
}

var minLon = Infinity;
var maxLon = -Infinity;
var minLat = Infinity;
var maxLat = -Infinity;

for(var i = 0; i < d.length; i++) {
var p = _computeBbox(d[i]);

minLon = Math.min(minLon, p[0]);
minLat = Math.min(minLat, p[1]);
maxLon = Math.max(maxLon, p[2]);
maxLat = Math.max(maxLat, p[3]);
}

return [
minLon, minLat,
maxLon, maxLat
];
}

// TODO `turf/bbox` gives wrong result when the input feature/geometry
// crosses the anti-meridian. We should try to implement our own bbox logic.
function computeBbox(d) {
function _computeBbox(d) {
return turfBbox(d);
}

11 changes: 10 additions & 1 deletion src/lib/topojson_utils.js
Original file line number Diff line number Diff line change
@@ -13,7 +13,16 @@ topojsonUtils.getTopojsonName = function(geoLayout) {
};

topojsonUtils.getTopojsonPath = function(topojsonURL, topojsonName) {
return topojsonURL + topojsonName + '.json';
var path = topojsonURL;

if(topojsonName.startsWith('un_')) {
path += 'un';
return 'https://raw.githubusercontent.com/etpinard/sane-topojson/refs/heads/un-borders/dist/un.json';
} else {
path += topojsonName;
}

return path + '.json';
};

topojsonUtils.getTopojsonFeatures = function(trace, topojson) {
15 changes: 9 additions & 6 deletions src/plots/geo/constants.js
Original file line number Diff line number Diff line change
@@ -141,14 +141,17 @@ exports.lataxisSpan = {
'*': 180
};

var world = {
lonaxisRange: [-180, 180],
lataxisRange: [-90, 90],
projType: 'equirectangular',
projRotate: [0, 0, 0]
};

// defaults for each scope
exports.scopeDefaults = {
world: {
lonaxisRange: [-180, 180],
lataxisRange: [-90, 90],
projType: 'equirectangular',
projRotate: [0, 0, 0]
},
un: world,
world: world,
usa: {
lonaxisRange: [-180, -50],
lataxisRange: [15, 80],
5 changes: 5 additions & 0 deletions src/plots/geo/geo.js
Original file line number Diff line number Diff line change
@@ -553,6 +553,7 @@ proto.makeFramework = function() {

// sane lonlat to px
_this.project = function(v) {
if(!v) return [null, null];
var px = _this.projection(v);
return px ?
[px[0] - _this.xaxis._offset, px[1] - _this.yaxis._offset] :
@@ -625,6 +626,8 @@ proto._render = function() {
var k;

function translatePoints(d) {
if(!d.lonlat) return null;

var lonlatPx = projection(d.lonlat);
return lonlatPx ?
strTranslate(lonlatPx[0], lonlatPx[1]) :
@@ -685,6 +688,8 @@ function getProjection(geoLayout) {
}

projection.isLonLatOverEdges = function(lonlat) {
if(!lonlat) return false;

if(projection(lonlat) === null) {
return true;
}
2 changes: 1 addition & 1 deletion src/plots/geo/layout_attributes.js
Original file line number Diff line number Diff line change
@@ -104,7 +104,7 @@ var attrs = module.exports = overrideAll({
scope: {
valType: 'enumerated',
values: sortObjectKeys(constants.scopeDefaults),
dflt: 'world',
dflt: 'un',
description: 'Set the scope of the map.'
},
projection: {
2 changes: 1 addition & 1 deletion src/plots/geo/layout_defaults.js
Original file line number Diff line number Diff line change
@@ -33,7 +33,7 @@ function handleGeoDefaults(geoLayoutIn, geoLayoutOut, coerce, opts) {
// no other scopes are allowed for 'albers usa' projection
if(isAlbersUsa) scope = geoLayoutOut.scope = 'usa';

var isScoped = geoLayoutOut._isScoped = (scope !== 'world');
var isScoped = geoLayoutOut._isScoped = (scope !== 'world' && scope !== 'un');
var isSatellite = geoLayoutOut._isSatellite = projType === 'satellite';
var isConic = geoLayoutOut._isConic = projType.indexOf('conic') !== -1 || projType === 'albers';
var isClipped = geoLayoutOut._isClipped = !!constants.lonaxisSpan[projType];
5 changes: 3 additions & 2 deletions src/traces/choropleth/plot.js
Original file line number Diff line number Diff line change
@@ -49,8 +49,9 @@ function calcGeoJSON(calcTrace, fullLayout) {
geoUtils.locationToFeature(locationmode, calcPt.loc, features);

if(feature) {
calcPt.geojson = feature;
calcPt.ct = feature.properties.ct;
var f0 = Array.isArray(feature) ? feature[0] : feature;
calcPt.geojson = f0;
calcPt.ct = f0.properties.ct;
calcPt._polygons = geoUtils.feature2polygons(feature);

var bboxFeature = geoUtils.computeBbox(feature);
8 changes: 4 additions & 4 deletions src/traces/scattergeo/hover.js
Original file line number Diff line number Diff line change
@@ -18,12 +18,12 @@ module.exports = function hoverPoints(pointData, xval, yval) {
var project = geo.project;

function distFn(d) {
var lonlat = d.lonlat;
var _lonlat = d.lonlat;

if(lonlat[0] === BADNUM) return Infinity;
if(isLonLatOverEdges(lonlat)) return Infinity;
if(!_lonlat || _lonlat[0] === BADNUM) return Infinity;
if(isLonLatOverEdges(_lonlat)) return Infinity;

var pt = project(lonlat);
var pt = project(_lonlat);
var px = project([xval, yval]);
var dx = Math.abs(pt[0] - px[0]);
var dy = Math.abs(pt[1] - px[1]);
14 changes: 9 additions & 5 deletions src/traces/scattergeo/plot.js
Original file line number Diff line number Diff line change
@@ -18,7 +18,10 @@ function plot(gd, geo, calcData) {
var gTraces = Lib.makeTraceGroups(scatterLayer, calcData, 'trace scattergeo');

function removeBADNUM(d, node) {
if(d.lonlat[0] === BADNUM) {
if(
d.lonlat &&
d.lonlat[0] === BADNUM
) {
d3.select(node).remove();
}
}
@@ -98,12 +101,13 @@ function calcGeoJSON(calcTrace, fullLayout) {
lonArray = [bboxGeojson[0], bboxGeojson[2]];
latArray = [bboxGeojson[1], bboxGeojson[3]];
} else {
lonArray = new Array(len);
latArray = new Array(len);
lonArray = [];
latArray = [];
for(i = 0; i < len; i++) {
calcPt = calcTrace[i];
lonArray[i] = calcPt.lonlat[0];
latArray[i] = calcPt.lonlat[1];
if(!calcPt.lonlat) continue;
lonArray.push(calcPt.lonlat[0]);
latArray.push(calcPt.lonlat[1]);
}

opts.ppad = calcMarkerSize(trace, len);
3 changes: 2 additions & 1 deletion test/plot-schema.json
Original file line number Diff line number Diff line change
@@ -2540,7 +2540,7 @@
"role": "object",
"scope": {
"description": "Set the scope of the map.",
"dflt": "world",
"dflt": "un",
"editType": "plot",
"valType": "enumerated",
"values": [
@@ -2549,6 +2549,7 @@
"europe",
"north america",
"south america",
"un",
"usa",
"world"
]