我正在构建一张显示美国地图的地图。在这张地图上,我正在绘制与尼尔森DMA地形相对应的热圈。
我使用的第一个topojson是这个Nielsen DMA topojson(来自simzhou&#39的回购here),用于在美国地图上直观地绘制这些热圈。
下面你可以看到带有DMA热圈的地图,以及完全由Nielsen DMA topojson构建的DMA边界线。
我遇到的问题是尝试绘制状态边框线,而不是这些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]
},
这是我到目前为止所做的事情。
正如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_dma
和states
几何形状的topojson。然而,这仍然不起作用,绘制状态线会带来混乱。
答案 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 web或reasonable size for web。如果你想使用mapshaper.org,你可以转换为topojson(并简化文件)。
对于未投影的美国geojson / topojson(长/纬对),您现在有两个共享相同坐标系的文件。 topojson变换对于每个变换都是不同的(如果两者都使用topojson),这是无关紧要的,重要的是底层坐标在相同的坐标空间中,而不是它们在topojson中的量化表示使用相同的变换。
这是使用未投影的美国州geojson的基本示例(来自第二个链接的geojson,转换为topojson):
https://bl.ocks.org/andrew-reid/178445c6acd84aa3b43525076f277157