D3.geo: Spherical arcs, not straight lines for parallels?

I just created a D3js globe localizer that looks like this:

enter image description here

If you look closely, the red square looks ugly as it does not follow the curve of the Earth. I have a bounding box in decimal degrees:

var bb = {W:-5.0, N:50.0, E:10.0, S:40.0 } 

And I draw the lines as follows:

 svg.append("path") .datum({type: "LineString", coordinates: [[-5, 40], [-5, 50], [10, 50], [10, 40], [-5, 40]] }) .attr("d", path); 

For large areas, this is even the opposite expectation curve (for the bounding box):

enter image description here

How to add pretty elegant spherical arcs?

+6
source share
2 answers

enter image description here

Given a known bounding box with decimal degrees ( search here for bb ), for example:

  bounds = [[-50.8,20.0][30,51.5]]; WNES0 = bounds[0][0], // West "W":-50.8 WNES1 = bounds[1][2], // North "N": 51.5 WNES2 = bounds[1][0], // East "E": 30 WNES3 = bounds[0][3], // South "S": 20.0 

Some mathematical data is needed.

 // *********** MATH TOOLKIT ********** // function parallel(φ, λ0, λ1) { if (λ0 > λ1) λ1 += 360; var dλ = λ1 - λ0, step = dλ / Math.ceil(dλ); return d3.range(λ0, λ1 + .5 * step, step).map(function(λ) { return [normalise(λ), φ]; }); } function normalise(x) { return (x + 180) % 360 - 180; } 

Then let both calculate the coordinates of the polygon and project it:

 // *********** APPEND SHAPES ********** // svg.append("path") .datum({type: "Polygon", coordinates: [ [[WNES0,WNES3]] .concat(parallel(WNES1, WNES0, WNES2)) .concat(parallel(WNES3, WNES0, WNES2).reverse()) ]}) .attr("d", path) .style({'fill': '#B10000', 'fill-opacity': 0.3, 'stroke': '#B10000', 'stroke-linejoin': 'round'}) .style({'stroke-width': 1 }); 

180th Meridian Crossing: Boxes on the 180th Meridian need special handling. For example, the localization of the Pacific Island complex between 155⁰ East and -155 West initially gives .... enter image description here ... with proper rotation (+ 180⁰): enter image description here ... and with the right boxing: enter image description here

The localizer is now perfect! Live demo on blocks

 var bb = { "item":"India", "W": 67.0, "N":37.5, "E": 99.0, "S": 5.0 }, localisator("body", 200, bb.item, bb.W, bb.N, bb.E, bb.S); 

enter image description here

+1 welcome.

+9
source

You can use the d3 built-in graticule generator to do this:

 var bb = {W: -5.0, N: 50.0, E: 10.0, S: 40.0 }; var arc = d3.geo.graticule() .majorExtent([[bb.W, bb.S], [bb.E, bb.N]]); 

Then use the outline function of the grid generator to draw the path:

 svg.append("path") .attr("class", "arc") .attr("d", path(arc.outline())); 

geographic 'arc'

A full working example can be found here .

+9
source

Source: https://habr.com/ru/post/974131/


All Articles