用两个量化/变换的topojsons建立一个统一的topojson?

时间:2018-05-31 21:28:55

标签: json d3.js geojson topojson quantization

背景

我正在构建一张显示美国地图的地图。在这张地图上,我正在绘制与尼尔森DMA地形相对应的热圈。

我使用的第一个topojson是这个Nielsen DMA topojson(来自simzhou&#39的回购here),用于在美国地图上直观地绘制这些热圈。

下面你可以看到带有DMA热圈的地图,以及完全由Nielsen DMA topojson构建的DMA边界线。

screen shot 2018-05-31 at 4 37 19 pm

问题:

我遇到的问题是尝试绘制状态边框线,而不是这些DMA边框线。我带来了" https://unpkg.com/us-atlas@1/us/10m.json"那@mbostock为我们提供了。通过topojson.feature(us, us.objects.states).features(我也试过topojson.mesh)绘制州边界时,当事情出错时就是这样。我99%肯定这是因为两个json文件使用不同的transform值,因此位置/坐标在不同的比例上变换。

以下是两个jsons:Nielsen DMA here和美国here

您可以在下面看到变换对象的不同之处:

来自US Atlas的

转换对象

"transform": {
       "scale": [0.009995801851947097,0.005844667153098606],
       "translate":[-56.77775821661018,12.469025989284091]
}
来自DMA topojson的

转换对象

"transform": {
        "scale": [0.00577894299429943, 0.002484260626062607],
        "translate": [-124.732975, 24.544237]
},

这是我到目前为止所做的事情。

的方法:

1。通过GeoJSON往返

正如Bostock here所详述的那样,我尝试通过GeoJSON的往返来制作一个新的topoJSON""

  

量化→非量化,去除量化。这通常是临时处理数据(例如,topojson.presimplify)。我想你可能想要这个,以便你可以将拓扑与不同的量化变换结合起来,但你总是可以通过GeoJSON进行往返来实现这一目标。

对于每个jsons 1.我将它们从topoJSON转换为geoJSON。 topo2geo nielsen_dma=us-dma-geo.json < us-dma-topo.json 现在,对于每个json,我们都有一个带有绝对坐标的特征集合。 2.使用新的geoJSON,然后我通过CLI将它们转换回topoJSON。 geo2topo nielsen_dma=us-dma-geo.json > us-dma-topo.json 两个JSON都不再具有transform属性,但它们具有bbox。 现在我有两个jsons从topojson往返 - &gt; geojson - &gt; topojson。 4.我从两个jsons中剥离了bbox个属性,因为它们是optional. 然后我简单地将几何集合添加到另一个。 statesJSON.objects.nielsen_dma = dmaJSON.objects.nielsen_dma

我现在有一个具有nielsen_dmastates几何形状的topojson。然而,这仍然不起作用,绘制状态线会带来混乱。

screen shot 2018-05-31 at 5 18 13 pm

在往返geoJSON的往返过程中,我是否未能删除两个jsons的坐标量化?

可能(红色)相关问题:

  1. 尼尔森DMA地图不包括阿拉斯加和夏威夷的几何图形。两个jsons之间的这种差异会导致这个问题吗?

1 个答案:

答案 0 :(得分:1)

当我第一次阅读本文时,我试图解决评论中的基本问题(我错过了标记,因为我假设显示地图的代码看起来有点不同 - 我为误读而道歉。然而,在第二次考试,我意识到,虽然这个问题是一个x,y problem,尝试解决导致对D3和topojson是AREN和一些有趣的问题#39;吨不清楚 - 但潜在问题仍然混合投影和未投影数据,所以我试图在这里解决x和y:

<强> Topojson

Topojson本质上是一种通过编码拓扑和可选的量化delta编码整数坐标来存储geojson特征或要素类的方法。 Topojson本身并没有改变底层坐标,它改变了它们的表现形式。

为了将topojson与D3一起使用,我们需要将其转换回geojson,因为D3 geoPaths只接受geojson - topojson.feature()返回geojson。

潜在的痛苦来源

最终的问题根本不是由topojson引起的。您有两个使用不同坐标系的拓扑源:

  • US json使用二维笛卡尔坐标空间(使用Albers投影投影的特征)。未压缩的坐标是SVG像素。

  • 尼尔森json使用纬度/经度坐标空间(3d地球上的点)。未压缩的坐标不是笛卡尔坐标(除非应用直板Carree投影:long = x,lat = y)。

当US json通过topojson.feature()时,返回的geojson将在大约[0,0],[960,600](在这种情况下)的边界框内具有x,y值。当任何未经投影的topojson(exielple的Nielsen json)通过topojson.feature()时,返回的geojson将在[-180,90],[180,-90]的边界框内具有long,lat值 - 就是它将具有有效的长/纬对。

这些基础和不同的坐标系是问题,而不是topojson中坐标的表示。

结合Topojson

我不确定你们如何将两者结合起来的细节。 topojson将geojson分成组成部分 - 弧和特征(引用弧并保持特征属性)。弧是以数字方式引用的 - 如果您没有修改索引,那么您就不能使用:

statesJSON.objects.nielsen_dma = dmaJSON.objects.nielsen_dma

但是,即使您确实修改了弧索引并引入了状态JSON但不在dmaJSON中的弧,您仍然会遇到问题。这是因为我们仍在使用不同的坐标系。

topojson使用的变换包括缩放和平移 - 投影数据使用Albers投影,未投影的数据不使用任何投影,但可以使用Plate Carree投影强制转换为x,y(长= X,LAT = Y)。但是Plate Carree的纬度是直的(它是一个等长的投影),而Albers的特征是弯曲的纬度(它是一个圆锥投影)。因此,每个坐标系中相同特征的形状将不同。每个坐标系统之间的方向也不同(东部不是Albers上大多数地方的直接右侧)。您无法使用平移和缩放修改形状和方向。

不同的Topojson变换

  

我99%肯定这是因为两个json文件使用不同的变换值,因此位置/坐标在不同的比例上变换。

使用具有相同变换值的两个topojson文件非常罕见,同样使用边界框。变换仅对于再现用于创建topojson的原始坐标至关重要。其值仅与将编码的topojson坐标转换回原始(geojson)坐标相关。变换特定于topojson的坐标。

最终,使用D3时变换无关:用于创建topojson的原始坐标是D3通过topojson.feature()实际使用的坐标。变换本质上是无关紧要的 - 只要它对编码和解码是恒定的。

如何解决此问题?

您有一个投影文件(US json),您不知道用于创建它的投影。在不知道用于创建它的投影的情况下,您无法在Nielsen数据上应用相同的投影。 即使您可以通过d3 geoProjection运行Nielsen数据,使其覆盖美国数据(使用空投影) - 您也不应该这样做。在缩放,平移或设置居中坐标等设置时,不同的坐标系统很麻烦 - 它需要单独的代码来处理未投影和投影的数据,基本上是复制代码

这意味着您需要为美国查找新的数据源。幸运的是,有很多在线资源,例如这里有两个:excessive size for webreasonable size for web。如果你想使用mapshaper.org,你可以转换为topojson(并简化文件)。

对于未投影的美国geojson / topojson(长/纬对),您现在有两个共享相同坐标系的文件。 topojson变换对于每个变换都是不同的(如果两者都使用topojson),这是无关紧要的,重要的是底层坐标在相同的坐标空间中,而不是它们在topojson中的量化表示使用相同的变换。

这是使用未投影的美国州geojson的基本示例(来自第二个链接的geojson,转换为topojson):

https://bl.ocks.org/andrew-reid/178445c6acd84aa3b43525076f277157