重叠地图之间的不精确

时间:2018-04-11 15:49:04

标签: d3.js data-visualization topojson

我创建了这张地图( PLUNKER )。

它通过坚果0(国家)来代表欧洲,如果你右键点击一个国家,这个县就会被缩放,它的地区(坚果2)会显示出来。

一段代码:

var projectionCurrent = d3.geoMercator() 
    .scale(1) 
    .translate([width / 2, height / 2]); 

var projectionBase = d3.geoMercator()
    .scale(1) 
    .translate([width / 2, height / 2]);

var path = d3.geoPath().projection(projectionCurrent);

var map = d3.select('#container-map');

var mapSvg = map.append('svg')
    .attr('id', 'container-map-svg')
    .attr('width', width)
    .attr('height', height);

var mapSvgG = mapSvg.append('g');

function makeMap(data) {
    var nuts0 = data[0];
    var nuts2 = data[1];
    var countries = topojson.feature(nuts0, nuts0.objects.nuts0);
    var regions = topojson.feature(nuts2, nuts2.objects.nuts2);
    projectionBase.fitSize([width, height], countries);
    projectionCurrent.fitSize([width, height], countries);

    mapSvgG.selectAll('path')
        .data(countries.features)
        .enter()
        .append('path')
        .attr('class', 'country')
        .attr('fill', 'steelblue')
        .style('stroke', 'white')
        .style('stroke-width', 1) 
        .attr('d', path)
        .attr('id', function(c) {
            return 'country' + c.properties.nuts_id; 
        })

        .on('mouseover', function(c) {
            d3.select(this)
                .attr('fill', 'white') 
                .raise();
        })
        .on('mouseout', function(c) {
            d3.select(this)
                .attr('fill', 'steelblue');
        })
        .on('contextmenu', function(d, i) {
            d3.event.preventDefault(); 
            d3.selectAll('.region').remove();

            var features = regions.features.filter(function(feature) { 
                return feature.properties.nuts_id.substring(0, 2) == d.properties.nuts_id;
            });

            mapSvg.selectAll(null)
                .data(features)
                .enter()
                .append('path')
                .attr('class', 'region')
                .attr('fill', 'tomato')
                .style('stroke', 'white')
                .style('stroke-width', 1) 
                .attr('d', path)
                .attr('id', function(r) {
                    return 'region' + r.properties.nuts_id;
                })
                .on('mouseover', function(r) {
                    d3.select(this)
                        .attr('fill', 'white') 
                        .raise();
                })
                .on('mouseout', function(r) {
                    d3.select(this)
                        .attr('fill', 'tomato');
                })
                .on('contextmenu', function(r, i) {
                    d3.event.preventDefault();
                    zoomCountries(projectionCurrent, projectionBase);
                    d3.selectAll('.region').remove();
                })
                .raise();

                var featureCollection = { 'type': 'FeatureCollection', 'features': features }
                var projectionEnd = d3.geoMercator();
                zoomCountries(projectionCurrent, projectionEnd.fitExtent([[50, 50], [width-50, height-50]], featureCollection));

            }); 

} 

问题在于,如果右键单击某个国家/地区,则会看到区域,并且区域附近存在一些不完善之处。

我认为图像可以更好地解释问题:

enter image description here

在这种情况下,我选择了瑞士。 您可以看到区域(红色),邻近国家(蓝色)和瑞士国家的白色路径。

我认为问题是我使用的json文件不是很精确。

原始文件是:

然后我用mapshaper简化它们(使用相同的设置)。 特别是:

  1. 我使用Visvalingam/weighted area算法0.70%简化了json文件。
  2. 我使用控制台执行一些命令,例如:filter 'name != "Iceland"'filter 'name != "Turkey"'(显然对于坚果2我取消了冰岛和土耳其,取消了所有地区)
  3. 我将文件导出为topoJson。
  4. 最后我使用Qgis删除了一些岛屿,另存为geoJson(我使用了我按照以下步骤操作:firstsecond
  5. 在Mapshaper中导入并导出为topoJson。
  6. 生成的文件是nuts0topojson3.jsonnuts2topojson3.json(我用来创建地图)。

    我希望这个问题不太明显。我该怎么办?

1 个答案:

答案 0 :(得分:4)

您的问题是由于简化 - 您大大简化了多边形,区域图层和国家/地区图层具有不同的区域权重,因此简化会更改每个图层的不同。

这一直是简化不同图层的问题。文件不是以这种差异开始的,因此您可以使用未简化的文件,但这样做太详细了。

相反,请为国家和地区使用简化的区域图层。每个区域都有一个标识符,用于组合国家/地区代码和数字(两个字母的国家/地区代码后跟一些数字)。我创建了一个新属性,使用以下命令标识区域文件中的国家/地区:

nuts2.objects.nuts2.geometries.forEach(function(n) {
  n.properties.country = n.properties.id.substring(0,2);
})

现在我们可以使用我们修改过的topojson并将其插入到mapshaper中并在控制台中应用溶解(在QGis中也可以轻松完成溶解,或者任何其他GIS平台)。在mapshaper中:

  • 导入topojson
  • 打开控制台
  • 输入dissolve country
  • 将溶解的图层导出为新的topojson文件

现在,有一点是objects.nuts0在这个新文件中不存在,因为我们使用了nuts2,所以为了清楚起见,我们可以将其修改为nuts0。我们也没有这些国家的所有房产,我们只有两位数的国家代码。这需要对代码进行一些调整才能访问country属性,而不是原始国家/地区图层中显示的ID。

由于我们有一个区域图层和一个国家图层,它们从同一个文件(区域图层)共享相同的边界,因此我们没有间隙或奇数重叠的问题。

根据你的傻瓜,这里是demonstration block。 (在我的仓促中,我更改了topojson文件名。)

这可以进一步优化,例如,如果我们将区域和国家组合到同一个topojson中,我们只需要加载一次几何体(并且当各国与区域共享弧时,加载的数据较少)。可以使用不同的数据准备或GIS叠加来保留已解散文件中每个国家/地区的国家/地区属性。