2

根据维基百科的 svg 世界地图,我需要计算每个国家的质心。d3 库支持路径的质心方法。在提供的 svg 文件中,包含每个国家/地区的路径坐标。例如德国:

我如何使用 svg 数据的属性“d”来计算 D3 语法中的质心?我需要它指向每个国家的质心。

4

2 回答 2

3

您应该考虑使用 Mike Bostock 库中的世界地图文件,因为 d3 示例将为这些投影和文件做好准备。一些世界地图在这里,例如: https ://github.com/mbostock/topojson

我认为这真的会简化你的生活,你可以使用 topojson 编写这样的代码:

var svg = d3.select('#yourmap').append('svg');

var g = svg.append('g')
    .style(//some styling, like stroke-width);

var projection = //your projection
    .scale(//your scale)
    .translate(//your width/2, height/2)
var path = d3.geo.path()
    .projection(projection

//read in your json file...

var world = topojson.feature(world.objects.countries).features //guessing at a potential structure of your file

g.selectAll('circle')
        .data(world)
      .enter().append('circle')
        .attr('transform', function(d) { return 'translate(' + path.centroid(d) + ')'; })
        .attr('r', //whatever you want your radius to be, in pixels);

除非您使用 Wikipedia SVG 有特殊原因?

于 2016-04-27T22:14:05.150 回答
2

您可以根据这个示例计算质心,取自这个问题。可能有一种更简单的方法,但是将它与 d3.js 一起使用可能是这样的:

function area(pts) {
    var area=0;
    var nPts = pts.length;
    var j=nPts-1;
    var p1; var p2;

    for (var i=0;i<nPts;j=i++) {
        p1=pts[i]; p2=pts[j];
        area+=p1.x*p2.y;
        area-=p1.y*p2.x;
    }
    area/=2;
    return area;
};

function computeCentroid(pts) {
    var nPts = pts.length;
    var x=0; var y=0;
    var f;
    var j=nPts-1;
    var p1; var p2;

    for (var i=0;i<nPts;j=i++) {
        p1=pts[i]; p2=pts[j];
        f=p1.x*p2.y-p2.x*p1.y;
        x+=(p1.x+p2.x)*f;
        y+=(p1.y+p2.y)*f;
    }

    f=area(pts)*6;
    return [x/f,y/f];
};

var path = d3.geo.path().projection(projection);

var map = chartSvg.selectAll('path.feature')
    .data(mapFiltered);
map.enter().append('path')
    .attr('class', 'feature');
map.attr('d', function(d, i){
    var pathString = path(d,i);
    var pathStringTrimmed = pathString.substring(1, pathString.length-1);
    var pathArray = pathStringTrimmed.split('L').map(function(d, i){var xy = d.split(','); return {x: ~~xy[0], y: ~~xy[1]};});
    console.log(computeCentroid(pathArray));
    return path(d,i);})

编辑:

此示例从具有规范化路径的 GeoJSON 文件开始。在您的 SVG 中,您必须自己规范化路径,因为未填充normalizedPathSegList属性。例如,您可以使用 Inkscape 将其保存为 pdf 并将其重新导入到 SVG 文件中。是一种使用 javascript 将所有相对路径转换为绝对路径的方法。

顺便说一句,解析原始 d 字符串的另一种方法是使用 SVGPathSegList.getItem() 查询每个元素的 SVGPathSegList。

但是要真正使用 d3 为您加载、投影和查找质心,如果您从默认的 GeoJSON 世界地图或您找到或制作的另一张地图开始,会容易得多。

于 2012-08-22T14:46:40.277 回答