【问题标题】:Building a uniform topojson with two quantized/transformed topojsons?用两个量化/转换的 topojson 构建一个统一的 topojson?
【发布时间】:2018-05-31 21:28:55
【问题描述】:

背景

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

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

您可以在下面看到地图,其中包含 DMA 热圈,以及完全由 Nielsen DMA topojson 构建的 DMA 边界线。

问题:

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

这是两个 json:Nielsen DMA here 和美国 here

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

变换对象来自美国地图集

"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 进行往返。

对于每个 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 几何形状的 topojson。然而这仍然不起作用,并且绘制状态线会带来混乱。

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

可能(ir)相关问题:

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

【问题讨论】:

  • 如果您将文件转换为 geojson,您可以看到坐标 - 它们不是纬度和经度对。您需要经度和纬度对才能使用 d3 投影来投影数据。此 US topojson 预投影用于空投影(每个坐标代表一个像素,而不是 3d 地球上的一个点)。这个answer 可能会有所帮助。最简单的解决方案是从here 之类的地方获取美国的 geojson/topojson。
  • @AndrewReid 我很欣赏评论和链接的方向。我将在下周深入研究并弄清楚这一点。谢谢!
  • Mapshaper.org 可以在 shape/topojson/geojson 之间进行转换。 topojson 的变换值仅用于底层坐标的压缩,它们不会修改投影(或缺少),因此您不能直接修改 topojson 以使一层的未投影经纬度(非笛卡尔)坐标匹配另一个的投影笛卡尔坐标。
  • 我很抱歉,在我的第一条评论中引用的 geojson 有点大(您可以使用 mapshaper 将其简化为更适合网络浏览器的大小)。但是使用它是非常可取的 - 否则你正在使用两个不同的坐标系(它们的不同不仅仅是平移和缩放 - 一个是投影的 2d 空间(使用 Albers 投影),另一个由 3d 地球上的点组成(和如果明确转录到笛卡尔坐标空间是 Plate Caree 投影)。使用所有经纬度或所有投影 x,y 可以更轻松地进行操作,确保特征重叠
  • (原始链接数据集确实具有所有状态,但由于某种原因,在我的复制和粘贴过程中,我丢失了一些状态,但当我意识到这一点时,我已经找到了一个较小的 geojson 并将其转换为块的 topojson:github.com/PublicaMundi/MappingAPI/blob/master/data/geojson/…)。

标签: json d3.js geojson topojson quantization


【解决方案1】:

当我第一次读到这篇文章时,我试图解决 cmets 中的潜在问题(我有点错过了标记,因为我认为显示地图的代码看起来与它可能的有点不同 - 我为误读道歉)。然而,在第二次检查中,我意识到虽然问题是x,y problem,但尝试的解决方案会导致一些关于 D3 和 topojson 的有趣问题,这些问题还不是很清楚 - 但根本问题仍然是混合投影数据和非投影数据,所以我'将尝试在此处同时处理 x 和 y:

Topojson

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

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

痛苦的根源

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

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

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

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

这些底层和不同的坐标系是问题所在,而不是 topojson 中坐标的表示。

结合Topojson

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

statesJSON.objects.nielsen_dma = dmaJSON.objects.nielsen_dma

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

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

不同的 Topojson 转换

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

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

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

我该如何解决这个问题?

您有一个投影文件(美国 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

【讨论】:

  • 感谢您进一步细化此问题。应用于 Bostock 的美国 json 的预投影确实是这个问题的根源。正如您建议的那样,解决方案很简单,采用未投影的美国各州 geoJSON(我将其转换为 topoJSON)并为两个 topoJSON 使用相同的路径生成器,我现在可以完美地叠加两张地图!我正要问是否仍然可以组合这两个 json(通过将一个对象添加到其他 objects 属性,但是您对构成一个 topoJSON 的弧 + 功能的解释似乎反驳了这一点。
  • 有一些方法可以组合两个 topojson - 例如使用 mapshaper(虽然我从来没有这样做过),当然它们仍然必须共享底层坐标系。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-12
  • 2017-10-31
  • 2013-05-31
  • 2015-07-29
  • 2016-02-28
相关资源
最近更新 更多