gpt4 book ai didi

d3.js - 将EPSG投影范围转换为D3.js map

转载 作者:行者123 更新时间:2023-12-04 16:30:56 24 4
gpt4 key购买 nike

给定一个EPSG预测(例如,这个阿拉巴马州的预测:[http://spatialreference.org/ref/epsg/26729/][1])

如何使用给定的WGS84投影范围,以便可以在D3.js投影中使用它们。

例如,您如何知道用于显示 map 的投影,旋转度或边界框?

最佳答案

这是一个相当复杂的问题。答案将根据您正在查看的空间引用(SRS,或坐标引用系统(CRS))系统以及最终目标而有所不同。

我在此答案中使用d3.js v4

简短答案:

For example, how would you know what projection, degree of rotation or bounding box to use to show the map?



没有一成不变的规则可以涵盖所有预测。查看投影参数通常可以为您提供足够的信息,以快速创建投影-假设投影在d3中是开箱即用的。

在设置参数时(例如何时旋转或何时居中,使用哪种平行线等),我可以提供的最佳建议是在细化投影时缩小显示,以便您可以看到每个参数的作用以及查找的位置。然后进行缩放或范围拟合。然后为您的边界框使用geojson验证器,例如 this one

最后,如果所有数据都已经投影在同一投影中,则始终可以使用投影数据并完全删除d3.geoProjection( this question),尝试定义投影是一个有争议的问题。

基准

我将很快指出,如果您查看基准之间的差异,这个问题可能会更加复杂。例如,您引用的SRS使用了 NAD27 datum。基准是地球形状的数学表示,NAD27与 NAD83WGS84有所不同,尽管所有单位均以度为单位,因为基准代表了地球的三维表面。如果要混合使用冲突基准的数据,则可能会遇到一些精度问题,例如,NAD27和NAD83之间的基准偏移根据您的需要并不是无关紧要的(维基百科屏幕截图,无法链接到图像):

enter image description here

如果由于使用多个基准而导致位置偏移是一个问题,则您需要多个d3才能将其转换为一个标准基准。 D3假定您将使用WGS84(GPS系统使用的基准)。如果这些转变不是问题,请忽略答案的这一部分。

示例投影

因此,让我们看看您的投影 EPSG:26729:
PROJCS["NAD27 / Alabama East",
GEOGCS["NAD27",
DATUM["North_American_Datum_1927",
SPHEROID["Clarke 1866",6378206.4,294.9786982138982,
AUTHORITY["EPSG","7008"]],
AUTHORITY["EPSG","6267"]],
PRIMEM["Greenwich",0,
AUTHORITY["EPSG","8901"]],
UNIT["degree",0.01745329251994328,
AUTHORITY["EPSG","9122"]],
AUTHORITY["EPSG","4267"]],
UNIT["US survey foot",0.3048006096012192,
AUTHORITY["EPSG","9003"]],
PROJECTION["Transverse_Mercator"],
PARAMETER["latitude_of_origin",30.5],
PARAMETER["central_meridian",-85.83333333333333],
PARAMETER["scale_factor",0.99996],
PARAMETER["false_easting",500000],
PARAMETER["false_northing",0],
AUTHORITY["EPSG","26729"],
AXIS["X",EAST],
AXIS["Y",NORTH]]

这是对投影的相当标准的描述。每种类型的投影都有其特定的参数,因此这些参数不一定总是相同的。

此描述中最重要的部分是:
NAD27 / Alabama East投影名称,不是必需的,但是一个很好的引用,因为它比EPSG编号更容易记住,并且引用/工具只能使用通用名称而不是EPSG编号。
PROJECTION["Transverse_Mercator"]我们正在处理的投影类型。这定义了如何将表示地球表面上的点的3d坐标转换为笛卡尔平面上的2d坐标。如果您在此处看到的投影不在d3支持的投影列表中( v3- v4),那么您在定义自定义投影时需要做一些工作。但是,通常您会找到与此匹配的投影。投影的类型会更改 map 是旋转还是以每个轴为中心。
PARAMETER["latitude_of_origin",30.5],
PARAMETER["central_meridian",-85.83333333333333],

这两个参数设置投影的中心。对于横向墨卡托,只有中央子午线很重要。 See this demo of the effect of choosing a central meridian on a transverse Mercator

原点纬度主要用于设置北向引用点。中央子午线对东边也是如此,但如上所述,设置中央子午线,使极点之间的失真最小化(等效于常规墨卡托上的赤道)。如果确实需要适当的北移和东移,以便可以比较纸质 map 和共享相同投影的网络 map 中的x,y位置,则d3可能不是最佳选择。如果您不关心在笛卡尔坐标空间中测量坐标,则这些参数无关紧要:D3不会复制投影的坐标系统(以英尺为单位测量为假的东/北),而是在SVG坐标中复制相同的形状空间。

因此,基于投影描述中的相关参数,以该投影的原点为中心的d3.geoProjection如下所示:
d3.geoTransverseMercator()
.rotate([85.8333,0])
.center([0,30.5])

为什么我旋转大约86度?这就是横向墨卡托的构建方式。在横向墨卡托的 demo中, map 沿x轴旋转。以x轴为中心只会简单地左右移动 map ,而不会更改投影的性质。在 demo中,很明显投影正发生与平移根本不同的变化,这是所应用的旋转。当我在投影下方旋转地球时,我使用的旋转为负数。因此,此投影的中心为西-85.833度或85.8333度。

由于在横轴墨卡托上,变形沿子午线是一致的,因此我们可以上下摇动而无需旋转。这就是为什么我在y轴上使用中心(在这种情况下以及其他情况下,也可以在y轴上旋转,且负y),因为这会使 map 下方的圆柱投影旋转,从而获得与平移相同的结果) 。

如果将我们缩小一点,则投影效果如下所示:

enter image description here

它可能看起来很扭曲,但仅用于显示阿拉巴马州及其附近的区域。放大它看起来看起来更正常了:

enter image description here

下一个问题自然是:规模如何?视视口(viewport)的大小和要显示的区域而定。并且,您的投影没有指定任何范围。如果您想显示 map 投影的范围,请在答案的末尾触及范围。即使投影有边界,它们也很可能与您要显示的区域不对齐(通常是整个投影边界的子集)。

那在其他地方居中呢?假设您只想显示一个不在投影中心的城镇?好吧,我们可以使用中心。因为我们在x轴上旋转了地球,所以任何定心都相对于中央子午线。以[1,30.5]为中心,将 map 以中心子午线以东1度(以西85.8333度)为中心。因此,x分量将相对于旋转,y分量将相对于赤道-其纬度。

如果坚持投影很重要,则需要这种奇怪的居中行为,如果不需要,则可以更简单地修改x旋转会更容易,这样您的投影看起来像:
d3.geoTransverseMercator()
.center([0,y])
.rotate([-x,0])
...

这将针对您的特定区域自定义横向墨卡托优化,但会以偏离您的起始投影为代价。

不同的投影类型

不同的投影可能具有不同的参数。例如,圆锥形投影可以具有一条(切线)或两条(割线),这些线表示投影与地球相交的点(因此变形最小化)。这些投影(例如Albers或Lambert Conformal)使用类似的中心定位方法(rotate -x,y中心),但具有附加参数来指定表示切线或割线的平行线:
d3.geoAlbers()
.rotate([-x,0])
.center([0,y])
.parallels([a,b])

See this answer on how to rotate/center an Albers(对于目前想到的所有圆锥形投影基本上相同)。

平面/方位投影(我尚未检查)很可能仅居中。但是,每个 map 投影的“居中”方法可能略有不同(通常是.rotate和.center的组合)。

关于如何设置不同的投影类型/家庭,有很多示例和特别的问题,这些应该对大多数特定的投影有所帮助。

边界框

但是,您可能有一个指定边界的投影。或更可能是 image with a bounds and a projection。在这种情况下,您将需要指定这些范围。最简单的方法是使用 .fitExtentd3.geoProjection()方法使用geojson功能:

projection.fitExtent(extent, object):

Sets the projection’s scale and translate to fit the specified GeoJSON object in the center of the given extent. The extent is specified as an array [[x₀, y₀], [x₁, y₁]], where x₀ is the left side of the bounding box, y₀ is the top, x₁ is the right and y₁ is the bottom. Returns the projection.



(另请参见 this question/answer)

我将使用问题 here中的示例来演示如何使用边界框来帮助定义投影。我们的目标是使用以下知识来投影 map below:它的投影和边界框(我很方便,并且找不到具有足够快的定义边界框的好的示例):

enter image description here

但是,在到达边界框坐标之前,让我们看一下投影。在这种情况下,它是 like:
PROJCS["ETRS89 / Austria Lambert",
GEOGCS["ETRS89",
DATUM["European_Terrestrial_Reference_System_1989",
SPHEROID["GRS 1980",6378137,298.257222101,
AUTHORITY["EPSG","7019"]],
AUTHORITY["EPSG","6258"]],
PRIMEM["Greenwich",0,
AUTHORITY["EPSG","8901"]],
UNIT["degree",0.01745329251994328,
AUTHORITY["EPSG","9122"]],
AUTHORITY["EPSG","4258"]],
UNIT["metre",1,
AUTHORITY["EPSG","9001"]],
PROJECTION["Lambert_Conformal_Conic_2SP"],
PARAMETER["standard_parallel_1",49],
PARAMETER["standard_parallel_2",46],
PARAMETER["latitude_of_origin",47.5],
PARAMETER["central_meridian",13.33333333333333],
PARAMETER["false_easting",400000],
PARAMETER["false_northing",400000],
AUTHORITY["EPSG","3416"],
AXIS["Y",EAST],
AXIS["X",NORTH]]

因为我们将让d3根据边界框选择比例尺和中心点,所以我们只关心几个参数:
PARAMETER["standard_parallel_1",49],
PARAMETER["standard_parallel_2",46],

这是两条割线, map 投影在其中截取地球表面。
   PARAMETER["central_meridian",13.33333333333333],

这是中央子午线,是我们用来沿x轴旋转投影的数字(就像想到的所有圆锥形投影一样)。

最重要的是:
PROJECTION["Lambert_Conformal_Conic_2SP"],

这条线为我们提供了投影族/类型。

总而言之,这给了我们类似:
d3.geoConicConformal()
.rotate([-13.33333,0]
.parallels([46,49])

现在,由以下限制定义的边界框:
  • 东:17.2度
  • 西:9.3度
  • 北:49.2度
  • 南:46.0​​度
  • .fitExtent(和 .fitSize)方法采用geojson对象,并适本地转换和缩放投影。我将在这里使用 .fitSize,因为它会跳过边界的边距( fitExtent允许提供边距,这是唯一的区别)。因此,我们需要使用这些界限创建一个geojson对象:
    var bbox = {          
    "type": "Polygon",
    "coordinates": [
    [
    [9.3, 49.2], [17.2, 49.2], [17.2, 46], [9.3, 46], [9.3,49.2]
    ]
    ]
    }

    记住要使用 right hand rule,并使其终点与起点相同(否则会产生无尽的悲伤)。

    现在,我们要做的就是调用此方法,然后进行投影。由于我正在使用图像来验证投影参数,因此我知道了想要的宽高比。如果您不知道纵横比,则可能会有一些多余的宽度或高度。这给了我类似的东西:
    var projection = d3.geoConicConformal()
    .parallels([46,49])
    .rotate([-13.333,0])
    .fitSize([width,height],bbox)

    以及一个看起来很高兴的最终产品,例如(请牢记一个大大降低采样的世界topojson):

    enter image description here

    关于d3.js - 将EPSG投影范围转换为D3.js map ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42259132/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com