2012-08-22 76 views
1

基于svg world map from wikipedia我需要计算每个国家的质心。 d3库支持centorid method for paths。在提供的svg文件中包含了每个国家的路径坐标。例如德国:计算质心d3

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

+0

[用D3.js计算SVG路径质心]的可能的副本(http://stackoverflow.com/questions/12062561/calculate-svg-path-centroid-with-d3-js) – nrabinowitz

+0

可能的重复:http:///stackoverflow.com/questions/12062561/calculate-svg-path-centroid-with-d3-js – nrabinowitz

回答

0

你应该考虑使用来自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); 

要不是有你是一个特别的原因使用维基百科SVG?

2

您可以根据example计算质心,取自this question。有可能是一个更简单的方法,但使用它与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属性没有被填充。例如,您可以通过将其保存为pdf并将其重新导入到SVG文件来完成Inkscape。 Here是一种通过javascript将所有相对路径转换为绝对路径的方法。

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

但是要真正使用d3为您加载,投影和找到质心,如果您使用默认的GeoJSON世界地图或使用另一个您找到或创建的世界地图,将会容易得多。

+0

computeCentroid方法很有用。但提供的worldmap.svg文件不包含GeoJSON表示法。这意味着不支持功能(例如多边形)。例如,德国不仅包含L参数,而且还包含v和h,如下面的摘录:'' – Oliver