重叠地图之间的不精确性
Imprecision between overlapping maps
我创建了这张地图(PLUNKER)。
它以 nuts0(国家/地区)表示欧洲,如果您右键单击一个国家/地区,则会缩放该国家/地区并显示其区域 (nuts2)。
一段代码:
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));
});
}
问题是,如果您右键单击某个国家/地区,您会看到地区以及地区附近的一些缺陷。
我认为一张图片能更好地解释问题:
在这种情况下,我选择了瑞士。
您可以看到地区(红色)、邻国(蓝色)和瑞士国家的路径(白色)。
我认为问题是我使用的 json 文件不是很精确。
原始文件是这些:
然后我用 mapshaper 简化了它们(使用相同的设置)。
特别是:
- 我在
0.70%
. 使用 Visvalingam/weighted area
算法简化了 json 文件
- 我使用控制台执行一些命令,例如:
filter 'name != "Iceland"'
和 filter 'name != "Turkey"'
(显然对于 nuts2,我消除了冰岛和土耳其,消除了它们的所有区域)
- 我将文件导出为 topoJson。
- 最后我使用Qgis删除了一些岛屿,保存为geoJson(我使用我按照以下步骤操作:first and second)
- 在 Mapshaper 中导入并导出为 topoJson。
生成的文件是 nuts0topojson3.json
和 nuts2topojson3.json
(我用来创建地图)。
我希望这个问题不那么明显。我该怎么办?
您的问题是由于简化引起的 - 您正在大量简化多边形,区域层和国家层具有不同的面积权重,因此简化对每个层的更改不同。
这将始终是简化不同层的问题。这些文件不会以这种差异开头,因此您可以使用未简化的文件,但这会过于详细。
而是对国家和地区使用简化的区域图层。每个地区都有一个由国家代码和数字(两个字母的国家代码后跟一些数字)组合而成的标识符。我创建了一个新的 属性,它使用以下方法在区域文件中标识国家/地区:
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。
由于我们有一个区域层和一个国家层共享来自同一文件(区域层)的相同边界,因此我们没有间隙或奇怪重叠的问题。
这是基于您的 plunkr 的 demonstration block。 (匆忙中,我更改了topojson文件名)。
这可以进一步优化,例如,如果我们将区域和国家合并到同一个 topojson 中,我们只需要加载一次几何(并且由于国家与区域共享弧,因此加载的数据更少) .也可以使用不同的数据准备或 GIS 叠加来保留解散文件中每个国家/地区的国家/地区属性。
我创建了这张地图(PLUNKER)。
它以 nuts0(国家/地区)表示欧洲,如果您右键单击一个国家/地区,则会缩放该国家/地区并显示其区域 (nuts2)。
一段代码:
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));
});
}
问题是,如果您右键单击某个国家/地区,您会看到地区以及地区附近的一些缺陷。
我认为一张图片能更好地解释问题:
在这种情况下,我选择了瑞士。 您可以看到地区(红色)、邻国(蓝色)和瑞士国家的路径(白色)。
我认为问题是我使用的 json 文件不是很精确。
原始文件是这些:
然后我用 mapshaper 简化了它们(使用相同的设置)。 特别是:
- 我在
0.70%
. 使用 - 我使用控制台执行一些命令,例如:
filter 'name != "Iceland"'
和filter 'name != "Turkey"'
(显然对于 nuts2,我消除了冰岛和土耳其,消除了它们的所有区域) - 我将文件导出为 topoJson。
- 最后我使用Qgis删除了一些岛屿,保存为geoJson(我使用我按照以下步骤操作:first and second)
- 在 Mapshaper 中导入并导出为 topoJson。
Visvalingam/weighted area
算法简化了 json 文件
生成的文件是 nuts0topojson3.json
和 nuts2topojson3.json
(我用来创建地图)。
我希望这个问题不那么明显。我该怎么办?
您的问题是由于简化引起的 - 您正在大量简化多边形,区域层和国家层具有不同的面积权重,因此简化对每个层的更改不同。
这将始终是简化不同层的问题。这些文件不会以这种差异开头,因此您可以使用未简化的文件,但这会过于详细。
而是对国家和地区使用简化的区域图层。每个地区都有一个由国家代码和数字(两个字母的国家代码后跟一些数字)组合而成的标识符。我创建了一个新的 属性,它使用以下方法在区域文件中标识国家/地区:
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。
由于我们有一个区域层和一个国家层共享来自同一文件(区域层)的相同边界,因此我们没有间隙或奇怪重叠的问题。
这是基于您的 plunkr 的 demonstration block。 (匆忙中,我更改了topojson文件名)。
这可以进一步优化,例如,如果我们将区域和国家合并到同一个 topojson 中,我们只需要加载一次几何(并且由于国家与区域共享弧,因此加载的数据更少) .也可以使用不同的数据准备或 GIS 叠加来保留解散文件中每个国家/地区的国家/地区属性。