使用两个 quantized/transformed topojson 构建一个统一的 topojson?

Building a uniform topojson with two quantized/transformed topojsons?

背景

我正在制作一张显示美国地图的地图。在这张地图上,我绘制了与 Nielsen DMA 地形相对应的热圈。

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

下面你可以看到地图,有 DMA 热圈,还有完全根据 Nielsen DMA 拓扑构建的 DMA 边界线json。

问题:

我遇到的问题是尝试绘制州边界线,而不是这些 DMA 边界线。我引入了@mbostock 为我们提供的“https://unpkg.com/us-atlas@1/us/10m.json”。当通过 topojson.feature(us, us.objects.states).features 绘制州边界时(我也尝试过 topojson.mesh),那就是事情出错的时候。我 99% 确定这是因为两个 json 文件使用不同的 transform 值,因此 positions/coordinates 以不同的比例进行转换。

这是两个 json:Nielsen DMA here and the US here

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

从美国地图集转换对象

"transform": {
       "scale": [0.009995801851947097,0.005844667153098606],
       "translate":[-56.77775821661018,12.469025989284091]
}

从 DMA 拓扑json

转换对象
"transform": {
        "scale": [0.00577894299429943, 0.002484260626062607],
        "translate": [-124.732975, 24.544237]
},

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

方法:

1。通过 GeoJSON 往返

如 Bostock 所详述 here 我已经尝试制作一个新的 topoJSON "via a round trip through GeoJSON."

Quantized → non-quantized, to remove quantization. This is often done temporarily to process data (for example, topojson.presimplify). I suppose you might want this so that you could combine topologies with different quantized transforms, but you could always do this by making a round trip through GeoJSON.

对于每个 json 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。 3. 现在我让两个 json 从 topojson -> geojson -> topojson 往返一次。 4. 我从两个 json 中删除了 bbox 属性,因为它们是 optional. 5. 然后我简单地将一个的几何集合添加到另一个。 statesJSON.objects.nielsen_dma = dmaJSON.objects.nielsen_dma

我现在有一个具有 nielsen_dmastates 几何形状的拓扑 json。然而这还是不行,画州界线会带来混乱。

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

可能(不)相关的问题:

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

当我第一次阅读这篇文章时,我试图解决评论中的潜在问题(为此我有点错过了标记,因为我认为显示地图的代码看起来有点不同可能是 - 我为误读道歉)。然而,在第二次检查中,我意识到虽然问题是 x,y problem,但尝试的解决方案导致了一些关于 D3 和 topojson 的有趣问题,这些问题并没有立即明确——但潜在的问题仍然是混合的投影和未投影数据,所以我将尝试在此处同时解决 x 和 y:

拓扑json

Topojson 本质上是一种通过编码拓扑和可选的量化增量编码整数坐标来存储 geojson 特征或特征 类 的方法。 Topojson 本身不会改变底层坐标,它会改变它们的表示。

为了在 D3 中使用 topojson,我们需要将其转换回 geojson,因为 D3 geoPaths 只接受 geojson - topojson.feature( ) returns地理json.

痛苦的根本来源

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

  • 美国json使用二维笛卡尔坐标space(用阿尔伯斯投影投影的特征)。未压缩的坐标是 SVG 像素。

  • Nielsen json 使用 latitude/longitude 坐标 space(3d 地球上的点)。未压缩坐标不是笛卡尔坐标(除非应用直线 Plate Carree 投影:long = x, lat = y)。

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

这些潜在的和不同的坐标系是问题所在,而不是拓扑中坐标的表示json。

组合拓扑json

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

statesJSON.objects.nielsen_dma = dmaJSON.objects.nielsen_dma

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

topojson 使用的变换包括缩放和平移 - 投影数据使用 Albers 投影,未投影数据不使用任何投影,但可以使用Plate Carree 投影(long=x,lat=y)。但是 Plate Carree 的纬度是直的(它是等距柱状投影),而 Albers 的纬度是弯曲的(它是圆锥投影)。因此,相同特征在每个坐标系中的形状将不同。每个坐标系之间的方向也会有所不同(在 Albers 上的大多数地方,东不是直接向右)。您不能使用平移和缩放修改形状和方向。

不同拓扑json变换

I am 99% sure that this is because the two json files are using different transform values, and therefore the positions/coordinates are transformed on different scales.

很少会使用两个具有相同变换值的拓扑json 文件,边界框也是如此。变换仅对再现用于创建拓扑 json 的原始坐标至关重要。它的值只与将编码的 topojson 坐标转换回原始 (geojson) 坐标有关。该变换特定于该拓扑 json 的坐标。

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

我该如何解决这个问题?

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

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

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

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

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