两个CRS间坐标运算的计算¶
- 作者
甚至鲁奥
- 最后更新
2021-02-10
介绍¶
使用时 projinfo -s {{crs_def}} -t {{crs_def}} , cs2cs {{crs_def}} {{crs_def}} 或者潜在的 proj_create_crs_to_crs()
或 proj_create_operations()
函数,PROJ应用一种算法来计算一个或多个候选坐标运算,这些运算可以表示为PROJ pipeline 在源CRS和目标CRS之间转换。这篇文档是关于这个算法的描述,找到实际操作应用到以后能够执行坐标变换。因此,这主要是关于围绕协调操作方法的元数据管理,而不是关于用于实现这些方法的实际数学。事实上,在proj6中,大约有60000行代码处理“元数据”管理(包括PROJ字符串之间的转换,所有CRS WKT变体),而纯计算部分只有30000行。
本文档旨在为开发人员提供代码的纯文本解释,但也为好奇的项目用户深入了解幕后的情况。重要的是要记住,它并不意味着应该如何计算坐标运算的最终真理来源。显然,实施选择和妥协是可以质疑的。
让我们从一个例子开始研究NAD27和NAD83地理CRS之间的操作:
$ projinfo -s NAD27 -t NAD83 --summary --spatial-test intersects --grid-check none
Candidate operations found: 10
DERIVED_FROM(EPSG):1312, NAD27 to NAD83 (3), 1.0 m, Canada
DERIVED_FROM(EPSG):1313, NAD27 to NAD83 (4), 1.5 m, Canada - NAD27, at least one grid missing
DERIVED_FROM(EPSG):1241, NAD27 to NAD83 (1), 0.15 m, USA - CONUS including EEZ
DERIVED_FROM(EPSG):1243, NAD27 to NAD83 (2), 0.5 m, USA - Alaska including EEZ
DERIVED_FROM(EPSG):1573, NAD27 to NAD83 (6), 1.5 m, Canada - Quebec, at least one grid missing
EPSG:1462, NAD27 to NAD83 (5), 1.0 m, Canada - Quebec, at least one grid missing
EPSG:9111, NAD27 to NAD83 (9), 1.5 m, Canada - Saskatchewan, at least one grid missing
unknown id, Ballpark geographic offset from NAD27 to NAD83, unknown accuracy, World, has ballpark transformation
EPSG:8555, NAD27 to NAD83 (7), 0.15 m, USA - CONUS and GoM, at least one grid missing
EPSG:8549, NAD27 to NAD83 (8), 0.5 m, USA - Alaska, at least one grid missing
该算法涉及的情况很多,所以我们将从最简单的情况到更复杂的情况进行解释。我们在这里记录了在Proj8.0.0中实现的这个算法的工作原理。某些示例的结果也可能对Proj数据库的内容和使用的Proj版本非常敏感。
从代码的角度来看,算法的入口点是C++。 osgeo::proj::operation::CoordinateOperation::createOperations()
方法。
它结合了几种策略:
在项目数据库中查找可用的操作
根据源CR和目标CR的性质,考虑对(源CR、目标CR)来合成操作。
地理CRS到地理CRS,具有已知标识符¶
在上面的两个地理CR的例子中,它们具有标识的标识符, (projinfo 在内部将NAD27解析为EPSG:4267,将NAD83解析为EPSG:4269)该算法将首先在 proj.db
如果有列出源和目标CRS之间的直接转换的记录。这些转换通常涉及 Helmert -基于网格的操作或基准面移动(可以进行更深奥的操作)。
将发出类似于以下内容的请求:
$ sqlite3 proj.db "SELECT auth_name, code, name, method_name, accuracy FROM \
coordinate_operation_view WHERE \
source_crs_auth_name = 'EPSG' AND \
source_crs_code = '4267' AND \
target_crs_auth_name = 'EPSG' AND \
target_crs_code = '4269'"
EPSG|1241|NAD27 to NAD83 (1)|NADCON|0.15
EPSG|1243|NAD27 to NAD83 (2)|NADCON|0.5
EPSG|1312|NAD27 to NAD83 (3)|NTv1|1.0
EPSG|1313|NAD27 to NAD83 (4)|NTv2|1.5
EPSG|1462|NAD27 to NAD83 (5)|NTv1|1.0
EPSG|1573|NAD27 to NAD83 (6)|NTv2|1.5
EPSG|8549|NAD27 to NAD83 (8)|NADCON5 (2D)|0.5
EPSG|8555|NAD27 to NAD83 (7)|NADCON5 (2D)|0.15
EPSG|9111|NAD27 to NAD83 (9)|NTv2|1.5
ESRI|108003|NAD_1927_To_NAD_1983_PR_VI|NTv2|0.05
既然我们已经找到了直接的变换,我们就不再尝试更复杂的研究了。在上面的结果集中可以注意到ESRI:108003操作已找到,但由于源和目标CR位于EPSG注册表中,并且EPSG注册表本身中的这些CR之间存在操作,来自其他权限的转换将被忽略(除非它们位于项目权限中,可以用作重写)。
由于这些结果都涉及不具有完美精度且不涵盖2个CRS使用区域的操作,因此PROJ综合了“NAD27到NAD83的大致地理偏移”操作(参见 Ballpark transformation )
坐标运算的过滤和排序¶
最后一步是根据相关性对结果进行过滤和排序。
过滤将考虑以下条件以决定必须保留或放弃哪些操作:
用户可能表示的最小精确度,
必须应用坐标操作的使用区域
如果缺少操作所需的网格,则必须将其丢弃。
排序算法决定了我们得到的操作的相关性顺序。比较函数比较两个操作对,以确定两者中哪一个最相关。这是由 operator ()
结构的方法。当比较两个操作时,使用以下标准。测试按下面列出的顺序执行:
考虑一个可以表示为PROJ操作字符串的操作(数据库可能会列出其方法尚未由PROJ实现的操作)
如果两个操作的评估结果与上述标准相同,则认为不包括合成大致垂直变换(存在大地水准面模型时发生)的操作更相关。
如果两个操作的评估结果与上述标准相同,则将不包括合成大致水平变换的操作视为更相关的操作。
将引用本地可用的移位网格的操作视为更相关的操作。
将引用proj datumgrid包中可用但不一定在本地可用的网格的操作视为更相关的操作
将具有已知精确度的操作视为更相关的操作。
如果两个操作具有未知的精度,则将使用网格的操作视为更相关的操作,如果另一个没有(基于网格的操作被假定为比依赖于几个参数的操作更精确)
将使用面积较大的操作视为更相关的操作(注:使用面积的计算是基于边界框的近似值)
认为更相关的操作具有更好的准确性。
在精度相同的情况下,将不使用网格的操作视为更相关的操作(仅使用参数的操作将更快)
考虑涉及较少转换步骤的操作(所考虑的转换步骤是在WKT输出中列出的步骤,而不是项目管道步骤)
为了完整性,如果在上述所有标准下,两个操作具有可比性,则认为名称较短的操作更相关,如果它们具有相同的长度,则考虑名称按词典顺序排在最后的操作(例如“foo to bar(3)”优先于“foo to bar(2)”)
备注
proj_trans()
,基于由返回的结果 proj_create_crs_to_crs()
由于上述算法,将不一定使用在第一位置列出的操作。 proj_trans()
具有更多的上下文,因为它有要转换的坐标,所以它可以将该坐标与操作的使用区域进行比较。通常,上述标准将有利于一个使用面积较大的操作,而不是另一个面积较小的操作,因为它更普遍适用。但一旦知道了坐标, proj_trans()
可以选择应用于要变换的坐标的使用区域较小的操作。
大地测量/地理CRS到大地测量/地理CRS,无已知标识符¶
在许多情况下,源和/或目标CRS没有标识符(没有标识符的WKT、项目字符串、..)第一步是尝试在 proj.db
与CRS性质相同的CRS,以标识其名称与提供给 createOperations()
方法。如果只有一个匹配,并且CRS在“计算上”是等价的,则使用CRS的代码进行进一步计算。
如果此搜索未成功,或者如果具有已知CRS标识符的前一个案例未在数据库中找到匹配项,则搜索将基于基准。即,在数据库中搜索其基准与源和目标CRS的基准匹配的地理CRS的列表(通过查询 geodetic_crs 数据库表)。如果数据有一个已知的标识符,我们将使用它,否则我们将根据数据名在数据库中查找等效的数据。
让我们考虑一下源CRS的数据是EPSG:6171“法国测地线研究1993”,目标CRS的基准是EPSG:6258“欧洲地球参考系1989”。为了EPSG:6171,有10个匹配的(未弃用的)大地测量CRS:
EPSG:4171,RGF93,地理2D
EPSG:4964,RGF93,地心
EPSG:4965,RGF93,地理3D
第7042页,RGF93(lon-lat),地理3D
EPSG:7084,RGF93(长纬度),地理2D
IGNF:RGF93,RGF93 cartesiennes地心,地心
IGNF:RGF93GDD,RGF93地理(dd),地理2D
IGNF:RGF93D,RGF93 geographiques(dd),地理3D
IGNF:RGF93G,RGF93地理(dms),地理2D
IGNF:RGF93GEO,三维(RG93),地理
EPSG数据集的前三个条目是典型的:对于每个基准面,可以定义地理2D CRS(纬度、经度)、地理3D CRS(纬度、经度、椭球体高度)和地心CRS。对于该特定情况,EPSG数据集还包括两个额外的定义,分别对应于经度、纬度 [椭球体高度] 坐标系,可在法国IGNF官方注册表中找到。该IGNF注册表还定义了地理2D CRS(具有额外的微妙之处,一个条目以十进制度为单位,另一个条目以度分秒为单位)、地理3D和地心。
为了EPSG:6258,有7个匹配的(未弃用的)大地测量CRS:
EPSG:4258,ETRS89,地理2D
EPSG:4936,ETRS89,地心
EPSG:4937,ETRS89,地理3D
IGNF:ETRS89,ETRS89 cartesiennes地心,地心
IGNF:ETRS89G,ETRS89 geographiques(dms),地理2D
IGNF:ETRS89GEO公司,ETRS89 geographiques(dms),地理3D
电子自旋共振:104129地理位置2D
因此,3个典型的EPSG条目,3个等价条目(地理CRS的长、纬度排序)和一个来自ESRI注册中心;
PROJ现在可以测试10 x 7个不同的源x目标crs组合,使用上一节介绍的数据库搜索方法。一旦其中一个组合返回至少一个非大概的组合,就使用来自该组合的结果集。然后,PROJ将在该转换之前添加源CRS和第一中间CRS之间的转换,并且将在末尾添加第二中间CRS和目标CRS之间的转换。这些转换是地理二维和地理三维CRS或地理二维/三维和地心CRS之间的转换。
这是由 createOperationsWithDatumPivot()
方法。
所以如果在第7042页,和地理坐标EPSG:4936,ETRS89,geocentric,one获取以下串联操作,链接轴顺序更改,RGF93和ETRS89之间的空地心平移(EPSG:1591),以及地理坐标和地心坐标之间的转换。由于初始操作和最终操作都是转换,因此假定此串联操作具有完美的精度,中间转换说明RGF93数据是ETRS89的一个实现,因此它们在大多数情况下是等效的。
$ projinfo -s EPSG:7042 -t EPSG:4936
Candidate operations found: 1
-------------------------------------
Operation No. 1:
unknown id, axis order change (geographic3D horizontal) + RGF93 to ETRS89 (1) + Conversion from ETRS89 (geog2D) to ETRS89 (geocentric), 0 m, France
PROJ string:
+proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=cart +ellps=GRS80
WKT2:2019 string:
CONCATENATEDOPERATION["axis order change (geographic3D horizontal) + RGF93 to ETRS89 (1) + Conversion from ETRS89 (geog2D) to ETRS89 (geocentric)",
SOURCECRS[
GEOGCRS["RGF93 (lon-lat)",
[...]
ID["EPSG",7042]]],
TARGETCRS[
GEODCRS["ETRS89",
[...]
ID["EPSG",4936]]],
STEP[
CONVERSION["axis order change (geographic3D horizontal)",
METHOD["Axis Order Reversal (Geographic3D horizontal)",
ID["EPSG",9844]],
ID["EPSG",15499]]],
STEP[
COORDINATEOPERATION["RGF93 to ETRS89 (1)",
[...]
METHOD["Geocentric translations (geog2D domain)",
ID["EPSG",9603]],
PARAMETER["X-axis translation",0,
LENGTHUNIT["metre",1],
ID["EPSG",8605]],
PARAMETER["Y-axis translation",0,
LENGTHUNIT["metre",1],
ID["EPSG",8606]],
PARAMETER["Z-axis translation",0,
LENGTHUNIT["metre",1],
ID["EPSG",8607]],
OPERATIONACCURACY[0.0],
ID["EPSG",1591],
REMARK["May be taken as approximate transformation RGF93 to WGS 84 - see code 1671."]]],
STEP[
CONVERSION["Conversion from ETRS89 (geog2D) to ETRS89 (geocentric)",
METHOD["Geographic/geocentric conversions",
ID["EPSG",9602]]]],
USAGE[
SCOPE["unknown"],
AREA["France"],
BBOX[41.15,-9.86,51.56,10.38]]]
大地测量/地理CRS到大地测量/地理CRS,无需直接转换¶
仍在考虑大地测量/地理CR之间的转换,但让我们考虑在数据库中查找源CR和目标CR之间的转换(可能根据上一节详述的相同数据通过“等效”CR)会导致一个空集。
当然,由于大多数操作是可逆的,因此首先尝试执行查找,切换源和目标CR,并反转生成的操作:
$ projinfo -s NAD83 -t NAD27 --spatial-test intersects --summary
Candidate operations found: 10
INVERSE(DERIVED_FROM(EPSG)):1312, Inverse of NAD27 to NAD83 (3), 2.0 m, Canada
INVERSE(DERIVED_FROM(EPSG)):1313, Inverse of NAD27 to NAD83 (4), 1.5 m, Canada - NAD27
INVERSE(DERIVED_FROM(EPSG)):1241, Inverse of NAD27 to NAD83 (1), 0.15 m, USA - CONUS including EEZ
INVERSE(DERIVED_FROM(EPSG)):1243, Inverse of NAD27 to NAD83 (2), 0.5 m, USA - Alaska including EEZ
INVERSE(DERIVED_FROM(EPSG)):1573, Inverse of NAD27 to NAD83 (6), 1.5 m, Canada - Quebec, at least one grid missing
INVERSE(EPSG):1462, Inverse of NAD27 to NAD83 (5), 2.0 m, Canada - Quebec, at least one grid missing
INVERSE(EPSG):9111, Inverse of NAD27 to NAD83 (9), 1.5 m, Canada - Saskatchewan, at least one grid missing
unknown id, Ballpark geographic offset from NAD83 to NAD27, unknown accuracy, World, has ballpark transformation
INVERSE(EPSG):8555, Inverse of NAD27 to NAD83 (7), 0.15 m, USA - CONUS and GoM, at least one grid missing
INVERSE(EPSG):8549, Inverse of NAD27 to NAD83 (8), 0.5 m, USA - Alaska, at least one grid missing
那是个简单的案子。现在让我们考虑一下澳大利亚CRS AGD84和GDA2020之间的转换。从AGD84到GDA2020没有直接转换,或者没有反向转换,即使考虑基于基础基准的替代大地测量CRS。然后,PROJ将在coordinateu operationu view表中执行交叉联接,以查找coordinate操作的元组(op1,op2),从而:
SOURCE_CRS=op1.SOURCE_CRS和op1.target_CRS=op2.SOURCE_CRS和op2.target_CRS=target_CRS或
SOURCEu CRS=op1.SOURCEu CRS和op1.targetu CRS=op2.targetu CRS和op2.SOURCEu CRS=targetu CRS或
SOURCEu CRS=op1.targetu CRS和op1.SOURCEu CRS=op2.SOURCEu CRS和op2.targetu CRS=targetu CRS或
SOURCEu CRS=op1.targetu CRS和op1.SOURCEu CRS=op2.targetu CRS和op2.SOURCEu CRS=targetu CRS
根据选择哪种情况,op1和op2应该在连接之前反转。
这个逻辑是由 findsOpsInRegistryWithIntermediate()
方法。
假设安装了proj datumgrid oceania包,我们将获得AGD84到GDA2020坐标操作查找的以下结果:
$ projinfo -s AGD84 -t GDA2020 --spatial-test intersects -o PROJ
Candidate operations found: 4
-------------------------------------
Operation No. 1:
unknown id, AGD84 to GDA94 (5) + GDA94 to GDA2020 (1), 0.11 m, Australia - AGD84
PROJ string:
+proj=pipeline +step +proj=axisswap +order=2,1 \
+step +proj=unitconvert +xy_in=deg +xy_out=rad \
+step +proj=hgridshift +grids=National_84_02_07_01.gsb \
+step +proj=push +v_3 \
+step +proj=cart +ellps=GRS80 \
+step +proj=helmert +x=0.06155 +y=-0.01087 +z=-0.04019 \
+rx=-0.0394924 +ry=-0.0327221 +rz=-0.0328979 \
+s=-0.009994 +convention=coordinate_frame \
+step +inv +proj=cart +ellps=GRS80 \
+step +proj=pop +v_3 \
+step +proj=unitconvert +xy_in=rad +xy_out=deg \
+step +proj=axisswap +order=2,1
-------------------------------------
Operation No. 2:
unknown id, AGD84 to GDA94 (2) + GDA94 to GDA2020 (1), 1.01 m, Australia - AGD84
PROJ string:
+proj=pipeline +step +proj=axisswap +order=2,1 \
+step +proj=unitconvert +xy_in=deg +xy_out=rad \
+step +proj=push +v_3 \
+step +proj=cart +ellps=aust_SA \
+step +proj=helmert +x=-117.763 +y=-51.51 +z=139.061 \
+rx=-0.292 +ry=-0.443 +rz=-0.277 +s=-0.191 \
+convention=coordinate_frame \
+step +proj=helmert +x=0.06155 +y=-0.01087 +z=-0.04019 \
+rx=-0.0394924 +ry=-0.0327221 +rz=-0.0328979 \
+s=-0.009994 +convention=coordinate_frame \
+step +inv +proj=cart +ellps=GRS80 \
+step +proj=pop +v_3 \
+step +proj=unitconvert +xy_in=rad +xy_out=deg \
+step +proj=axisswap +order=2,1
-------------------------------------
Operation No. 3:
unknown id, AGD84 to GDA94 (5) + GDA94 to GDA2020 (2), 0.15 m, unknown domain of validity
PROJ string:
+proj=pipeline +step +proj=axisswap +order=2,1 \
+step +proj=unitconvert +xy_in=deg +xy_out=rad \
+step +proj=hgridshift +grids=National_84_02_07_01.gsb \
+step +proj=hgridshift +grids=GDA94_GDA2020_conformal_and_distortion.gsb \
+step +proj=unitconvert +xy_in=rad +xy_out=deg \
+step +proj=axisswap +order=2,1
-------------------------------------
Operation No. 4:
unknown id, AGD84 to GDA94 (5) + GDA94 to GDA2020 (3), 0.15 m, unknown domain of validity
PROJ string:
+proj=pipeline +step +proj=axisswap +order=2,1 \
+step +proj=unitconvert +xy_in=deg +xy_out=rad \
+step +proj=hgridshift +grids=National_84_02_07_01.gsb \
+step +proj=hgridshift +grids=GDA94_GDA2020_conformal.gsb \
+step +proj=unitconvert +xy_in=rad +xy_out=deg \
+step +proj=axisswap +order=2,1
可以看到所选择的已使用的中间CRS是GDA94。这是PROJ.6的一个全新行为,与PROJ.4的逻辑相反,PROJ.4中的数据转换意味着使用EPSG:4326/WGS 84具有强制基准中心。PROJ 6不再将其硬编码为强制数据中心,而是依赖数据库来查找适当的中心。实际上,在上述查找过程中考虑了WGS 84,因为AGD84和WGS 84以及WGS 84和GDA2020之间存在转换。但是,我们之前没有提到过过滤的最后一步,也没有提到过过滤的最后一步。在排序结果列表中,给定使用区域相同的两个操作A和B,如果B的精度低于A,并且A不使用网格,或者所有需要的网格都可用,那么B将被丢弃。
如果强制基准毂被视为EPSG:4326,得到:
$ projinfo -s AGD84 -t GDA2020 --spatial-test intersects --pivot-crs EPSG:4326 -o PROJ
Candidate operations found: 2
-------------------------------------
Operation No. 1:
unknown id, AGD84 to WGS 84 (7) + Inverse of GDA2020 to WGS 84 (2), 4 m, Australia - AGD84
PROJ string:
+proj=pipeline +step +proj=axisswap +order=2,1 \
+step +proj=unitconvert +xy_in=deg +xy_out=rad \
+step +proj=push +v_3 \
+step +proj=cart +ellps=aust_SA \
+step +proj=helmert +x=-117.763 +y=-51.51 +z=139.061 \
+rx=-0.292 +ry=-0.443 +rz=-0.277 \
+s=-0.191 +convention=coordinate_frame \
+step +inv +proj=cart +ellps=GRS80 \
+step +proj=pop +v_3 \
+step +proj=unitconvert +xy_in=rad +xy_out=deg \
+step +proj=axisswap +order=2,1
-------------------------------------
Operation No. 2:
unknown id, AGD84 to WGS 84 (9) + Inverse of GDA2020 to WGS 84 (2), 4 m, Australia - AGD84
PROJ string:
+proj=pipeline +step +proj=axisswap +order=2,1 \
+step +proj=unitconvert +xy_in=deg +xy_out=rad \
+step +proj=hgridshift +grids=National_84_02_07_01.gsb \
+step +proj=unitconvert +xy_in=rad +xy_out=deg \
+step +proj=axisswap +order=2,1
这些操作精度较低,因为假定WGS 84相当于GDA2020,精度为4米。这是一个例子,表明使用WGS 84作为枢纽系统可能是次优的。
由于没有这样的中心,仍然存在试图找到中心CRS不起作用的情况。例如,当在编写WGS 84、WGS 84(G1762)时从GDA94转换到最新实现时,可能会发生这种情况。WGS 84(G1762)之间存在转换。使用上述技术,我们只能找到一个非大概的操作:1。从GDA94(geog2D)到GDA94(地心)的转换:由PROJ 2合成。ITRF2008与GDA94(1)的反比:来自EPSG 3。WGS 84(G1762)与ITRF2008(1)的反比:来自EPSG 4。从WGS 84(G1762)(地心)到WGS 84(G1762)的转换:由项目合成
这还不错,但全球的有效使用区域是“澳大利亚--陆上和专属经济区”,而GDA94的使用区域更大。还有一条路可以通过GDA2020而不是ITRF2008来走。GDA94到GDA2020的转换在各自的地理CRS上运行,而GDA2020到WGS 84(G1762)的转换在地心CRS上运行。因此,GDA2020不能被坐标操作表上的“简单”自联接SQL请求标识为HUB。这需要基于每个操作的源和目标CRS所引用的数据进行连接,而不是基于源和目标CRS本身。当存在匹配项时,Proj会在地理CRS和地心CRS之间插入所需的转换,以获得一致的串联操作,如下所示:1.GDA94到GDA2020(1):从EPSG 2.从GDA2020(Geog2D)到GDA2020(地心):由Proj 3.GDA2020到WGS 84(G1762)(1):从EPSG 4.从WGS 84(G1762)(地心)到WGS 84(G1762)(Geog2D):由Proj合成
投射到任何目标CRS的CRS¶
这实际上扩展到任何派生的CRS,其投影CRS是众所周知的特殊情况。这种转换分两步进行:
使用导出的CR到其基础CR的逆转换,通常是逆地图投影。
找到从这个基本CRS到目标CRS的转换。如果基本CRS是目标CRS,则可以跳过该步骤。
$ projinfo -s EPSG:32631 -t RGF93
Candidate operations found: 1
-------------------------------------
Operation No. 1:
unknown id, Inverse of UTM zone 31N + Inverse of RGF93 to WGS 84 (1), 1 m, France
PROJ string:
+proj=pipeline +step +inv +proj=utm +zone=31 +ellps=WGS84 +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1
这是由 createOperationsDerivedTo
方法
对于对称情况,源CRS到导出的CRS,通过切换源CRS和目标CRS,然后反转得到的操作来应用上述算法。这主要是为了避免编写两次非常相似的代码。当考虑两种不同类型对象之间的转换时,此逻辑也适用于以下所有情况。
垂直CRS到地理CRS¶
这种转换通常并不意味着被项目用户用作独立的,而是作为复合CRS到目标CRS的内部计算步骤。
如果我们幸运的话,PROJ数据库将在以下两者之间注册转换:
$ projinfo -s "NAVD88 height" -t "NAD83(2011)" -o PROJ --spatial-test intersects
Candidate operations found: 11
-------------------------------------
Operation No. 1:
INVERSE(DERIVED_FROM(EPSG)):9229, Inverse of NAD83(2011) to NAVD88 height (3), 0.015 m, USA - CONUS - onshore
PROJ string:
+proj=vgridshift +grids=g2018u0.gtx +multiplier=1
但在没有匹配的情况下 createOperationsVertToGeog
该方法将用于综合一个大致的垂直变换,只考虑单位的变化,并在垂直CRS是深度而不是高度的情况下进行轴反转。当然,这样一个操作的结果是值得怀疑的,因此,一个大概的限定词和一个未知的准确性广告这样一个操作。
垂直CRS到垂直CRS¶
总体逻辑与上述情况类似。PROJ数据库中可能有直接操作,包括网格转换或简单偏移。后备方案是综合一个大概的转变。
这是由 createOperationsVertToVert
方法
$ projinfo -s "NGVD29 depth (ftUS)" -t "NAVD88 height" --spatial-test intersects -o PROJ
Candidate operations found: 3
-------------------------------------
Operation No. 1:
unknown id, Inverse of NGVD29 height (ftUS) to NGVD29 depth (ftUS) + NGVD29 height (ftUS) to NGVD29 height (m) + NGVD29 height (m) to NAVD88 height (3), 0.02 m, USA - CONUS east of 89°W - onshore
PROJ string:
+proj=pipeline +step +proj=axisswap +order=1,2,-3 +step +proj=unitconvert +z_in=us-ft +z_out=m +step +proj=vgridshift +grids=vertcone.gtx +multiplier=0.001
-------------------------------------
Operation No. 2:
unknown id, Inverse of NGVD29 height (ftUS) to NGVD29 depth (ftUS) + NGVD29 height (ftUS) to NGVD29 height (m) + NGVD29 height (m) to NAVD88 height (2), 0.02 m, USA - CONUS 89°W-107°W - onshore
PROJ string:
+proj=pipeline +step +proj=axisswap +order=1,2,-3 +step +proj=unitconvert +z_in=us-ft +z_out=m +step +proj=vgridshift +grids=vertconc.gtx +multiplier=0.001
-------------------------------------
Operation No. 3:
unknown id, Inverse of NGVD29 height (ftUS) to NGVD29 depth (ftUS) + NGVD29 height (ftUS) to NGVD29 height (m) + NGVD29 height (m) to NAVD88 height (1), 0.02 m, USA - CONUS west of 107°W - onshore
PROJ string:
+proj=pipeline +step +proj=axisswap +order=1,2,-3 +step +proj=unitconvert +z_in=us-ft +z_out=m +step +proj=vgridshift +grids=vertconw.gtx +multiplier=0.001
复合CRS到地理CRS¶
复合CRS的典型示例是由作为水平分量的地理或投影CRS和垂直CRS构成的CRS。E、 g.“NAD83+NAVD88高度”
当复合源CRS的水平分量是投影CRS时,我们首先寻找从该源CRS到由投影CRS的地理CRS基部构成的另一复合CRS的操作,例如“NAD83/加利福尼亚1区(ftUS)+NAVD88高度”到“NAD83+NAVD88高度”,其最终进入上述情况之一。然后,我们可以考虑从一个地理CRS组成的复合CRS到另一个地理CRS的转换。
它首先从源复合CRS的垂直CRS到目标地理CRS的垂直转换开始,使用中详述的策略 Vertical CRS to a Geographic CRS
我们没有提到的是,当垂直CR和目标地理CR之间没有注册转换时,PROJ会尝试找到该垂直CR和任何其他地理CR之间的转换。这显然是一个近似值。如果对目标地理CR的垂直CR的研究导致使用不可用网格的操作,作为另一种近似,我们研究从垂直CR到垂直分量的源地理CR的操作。
一旦我们得到这些或多或少精确的垂直变换,我们就必须考虑水平变换。该算法对所有发现的垂直变换进行迭代,寻找它们的目标地理坐标系。这将用作水平变换的插值CR。然后,PROJ将寻找从源地理CRS到插值CRS以及从插值CRS到目标地理CRS的可用转换。然后是一个三级循环,用于创建链接在一起的最后一组操作:
从源地理坐标系到插值坐标系的水平变换
源垂直CRS到插值CRS的垂直变换
从插值CRS到目标地理CRS的水平变换。
这是由 createOperationsCompoundToGeog
方法
例子:
$ projinfo -s "NAD83(NSRS2007) + NAVD88 height" -t "WGS 84 (G1762)" --spatial-test intersects --summary
Candidate operations found: 21
unknown id, Inverse of NAD83(NSRS2007) to NAVD88 height (1) + NAD83(NSRS2007) to WGS 84 (1) + WGS 84 to WGS 84 (G1762), 3.05 m, USA - CONUS - onshore
unknown id, Inverse of NAD83(HARN) to NAD83(NSRS2007) (1) + Inverse of NAD83(HARN) to NAVD88 height (7) + NAD83(HARN) to WGS 84 (1) + WGS 84 to WGS 84 (G1762), 3.15 m, USA - CONUS south of 41°N, 95°W to 78°W - onshore
unknown id, Inverse of NAD83(HARN) to NAD83(NSRS2007) (1) + Inverse of NAD83(HARN) to NAVD88 height (7) + NAD83(HARN) to WGS 84 (3) + WGS 84 to WGS 84 (G1762), 3.15 m, USA - CONUS south of 41°N, 95°W to 78°W - onshore
unknown id, Inverse of NAD83(HARN) to NAD83(NSRS2007) (1) + Inverse of NAD83(HARN) to NAVD88 height (6) + NAD83(HARN) to WGS 84 (1) + WGS 84 to WGS 84 (G1762), 3.15 m, USA - CONUS south of 41°N, 112°W to 95°W - onshore
unknown id, Inverse of NAD83(HARN) to NAD83(NSRS2007) (1) + Inverse of NAD83(HARN) to NAVD88 height (6) + NAD83(HARN) to WGS 84 (3) + WGS 84 to WGS 84 (G1762), 3.15 m, USA - CONUS south of 41°N, 112°W to 95°W - onshore
unknown id, Inverse of NAD83(HARN) to NAD83(NSRS2007) (1) + Inverse of NAD83(HARN) to NAVD88 height (2) + NAD83(HARN) to WGS 84 (1) + WGS 84 to WGS 84 (G1762), 3.15 m, USA - CONUS north of 41°N, 112°W to 95°W
unknown id, Inverse of NAD83(HARN) to NAD83(NSRS2007) (1) + Inverse of NAD83(HARN) to NAVD88 height (2) + NAD83(HARN) to WGS 84 (3) + WGS 84 to WGS 84 (G1762), 3.15 m, USA - CONUS north of 41°N, 112°W to 95°W
unknown id, Inverse of NAD83(HARN) to NAD83(NSRS2007) (1) + Inverse of NAD83(HARN) to NAVD88 height (3) + NAD83(HARN) to WGS 84 (1) + WGS 84 to WGS 84 (G1762), 3.15 m, USA - CONUS north of 41°N, 95°W to 78°W
unknown id, Inverse of NAD83(HARN) to NAD83(NSRS2007) (1) + Inverse of NAD83(HARN) to NAVD88 height (3) + NAD83(HARN) to WGS 84 (3) + WGS 84 to WGS 84 (G1762), 3.15 m, USA - CONUS north of 41°N, 95°W to 78°W
unknown id, Inverse of NAD83(HARN) to NAD83(NSRS2007) (1) + Inverse of NAD83(HARN) to NAVD88 height (5) + NAD83(HARN) to WGS 84 (1) + WGS 84 to WGS 84 (G1762), 3.15 m, USA - CONUS south of 41°N, west of 112°W - onshore
unknown id, Inverse of NAD83(HARN) to NAD83(NSRS2007) (1) + Inverse of NAD83(HARN) to NAVD88 height (5) + NAD83(HARN) to WGS 84 (3) + WGS 84 to WGS 84 (G1762), 3.15 m, USA - CONUS south of 41°N, west of 112°W - onshore
unknown id, Inverse of NAD83(HARN) to NAD83(NSRS2007) (1) + Inverse of NAD83(HARN) to NAVD88 height (1) + NAD83(HARN) to WGS 84 (1) + WGS 84 to WGS 84 (G1762), 3.15 m, USA - CONUS north of 41°N, west of 112°W - onshore
unknown id, Inverse of NAD83(HARN) to NAD83(NSRS2007) (1) + Inverse of NAD83(HARN) to NAVD88 height (1) + NAD83(HARN) to WGS 84 (3) + WGS 84 to WGS 84 (G1762), 3.15 m, USA - CONUS north of 41°N, west of 112°W - onshore
unknown id, Inverse of NAD83(HARN) to NAD83(NSRS2007) (1) + Inverse of NAD83(HARN) to NAVD88 height (4) + NAD83(HARN) to WGS 84 (1) + WGS 84 to WGS 84 (G1762), 3.15 m, USA - CONUS north of 41°N, east of 78°W - onshore
unknown id, Inverse of NAD83(HARN) to NAD83(NSRS2007) (1) + Inverse of NAD83(HARN) to NAVD88 height (4) + NAD83(HARN) to WGS 84 (3) + WGS 84 to WGS 84 (G1762), 3.15 m, USA - CONUS north of 41°N, east of 78°W - onshore
unknown id, Inverse of NAD83(HARN) to NAD83(NSRS2007) (1) + Inverse of NAD83(HARN) to NAVD88 height (8) + NAD83(HARN) to WGS 84 (1) + WGS 84 to WGS 84 (G1762), 3.15 m, USA - CONUS south of 41°N, east of 78°W - onshore
unknown id, Inverse of NAD83(HARN) to NAD83(NSRS2007) (1) + Inverse of NAD83(HARN) to NAVD88 height (8) + NAD83(HARN) to WGS 84 (3) + WGS 84 to WGS 84 (G1762), 3.15 m, USA - CONUS south of 41°N, east of 78°W - onshore
unknown id, Ballpark geographic offset from NAD83(NSRS2007) to NAD83(FBN) + Inverse of NAD83(FBN) to NAVD88 height (1) + Ballpark geographic offset from NAD83(FBN) to WGS 84 (G1762), unknown accuracy, USA - CONUS - onshore, has ballpark transformation
unknown id, Ballpark geographic offset from NAD83(NSRS2007) to NAD83(2011) + Inverse of NAD83(2011) to NAVD88 height (3) + Ballpark geographic offset from NAD83(2011) to WGS 84 (G1762), unknown accuracy, USA - CONUS - onshore, has ballpark transformation
unknown id, Ballpark geographic offset from NAD83(NSRS2007) to NAD83(2011) + Inverse of NAD83(2011) to NAVD88 height (3) + Conversion from NAD83(2011) (geog2D) to NAD83(2011) (geocentric) + Inverse of ITRF2008 to NAD83(2011) (1) + Inverse of WGS 84 (G1762) to ITRF2008 (1) + Conversion from WGS 84 (G1762) (geocentric) to WGS 84 (G1762) (geog2D), unknown accuracy, USA - CONUS - onshore, has ballpark transformation
unknown id, NAD83(NSRS2007) to WGS 84 (1) + WGS 84 to WGS 84 (G1762) + Transformation from NAVD88 height to WGS 84 (G1762) (ballpark vertical transformation, without ellipsoid height to vertical height correction), unknown accuracy, USA - CONUS and Alaska; PRVI, has ballpark transformation
复合材料至复合材料¶
与上一段有些相似之处。我们首先研究了两个垂直CRS之间的垂直变换。
如果有这样的转换,可以是直接的,或者两个垂直的CR都与一个公共的中间CR有关。如果它有一个注册的插值地理CRS,则使用它。否则我们退回到源CRS的地理CRS。
最后,一个三级循环,用于创建链接在一起的最后一组操作:
从源CRS到插值CRS的水平变换
垂直变换
从插值CRS到目标CRS的水平变换。
例子:
$ projinfo -s "NAD27 + NGVD29 height (ftUS)" -t "NAD83 + NAVD88 height" --spatial-test intersects --summary Candidate operations found: 20 unknown id, NGVD29 height (ftUS) to NAVD88 height (3) + NAD27 to NAD83 (1), 0.17 m, USA - CONUS east of 89°W - onshore unknown id, NGVD29 height (ftUS) to NAVD88 height (2) + NAD27 to NAD83 (1), 0.17 m, USA - CONUS 89°W-107°W - onshore unknown id, NGVD29 height (ftUS) to NAVD88 height (1) + NAD27 to NAD83 (1), 0.17 m, USA - CONUS west of 107°W - onshore unknown id, NGVD29 height (ftUS) to NAVD88 height (3) + NAD27 to NAD83 (3), 1.02 m, unknown domain of validity unknown id, NGVD29 height (ftUS) to NAVD88 height (2) + NAD27 to NAD83 (3), 1.02 m, unknown domain of validity unknown id, NGVD29 height (ftUS) to NAVD88 height (1) + NAD27 to NAD83 (3), 1.02 m, unknown domain of validity unknown id, NGVD29 height (ftUS) to NAVD88 height (3) + NAD27 to NAD83 (5), 1.02 m, unknown domain of validity, at least one grid missing unknown id, NGVD29 height (ftUS) to NAVD88 height (3) + NAD27 to NAD83 (6), 1.52 m, unknown domain of validity, at least one grid missing unknown id, NGVD29 height (ftUS) to NAVD88 height (2) + NAD27 to NAD83 (9), 1.52 m, unknown domain of validity, at least one grid missing unknown id, NGVD29 height (ftUS) to NAVD88 height (1) + NAD27 to NAD83 (9), 1.52 m, unknown domain of validity, at least one grid missing unknown id, NGVD29 height (ftUS) to NAVD88 height (3) + Ballpark geographic offset from NAD27 to NAD83, unknown accuracy, USA - CONUS east of 89°W - onshore, has ballpark transformation unknown id, NGVD29 height (ftUS) to NAVD88 height (2) + Ballpark geographic offset from NAD27 to NAD83, unknown accuracy, USA - CONUS 89°W-107°W - onshore, has ballpark transformation unknown id, NGVD29 height (ftUS) to NAVD88 height (1) + Ballpark geographic offset from NAD27 to NAD83, unknown accuracy, USA - CONUS west of 107°W - onshore, has ballpark transformation unknown id, Transformation from NGVD29 height (ftUS) to NAVD88 height (ballpark vertical transformation) + NAD27 to NAD83 (1), unknown accuracy, USA - CONUS including EEZ, has ballpark transformation unknown id, Transformation from NGVD29 height (ftUS) to NAVD88 height (ballpark vertical transformation) + NAD27 to NAD83 (3), unknown accuracy, Canada, has ballpark transformation unknown id, Transformation from NGVD29 height (ftUS) to NAVD88 height (ballpark vertical transformation) + NAD27 to NAD83 (4), unknown accuracy, Canada - NAD27, has ballpark transformation unknown id, Transformation from NGVD29 height (ftUS) to NAVD88 height (ballpark vertical transformation) + NAD27 to NAD83 (5), unknown accuracy, Canada - Quebec, has ballpark transformation, at least one grid missing unknown id, Transformation from NGVD29 height (ftUS) to NAVD88 height (ballpark vertical transformation) + NAD27 to NAD83 (6), unknown accuracy, Canada - Quebec, has ballpark transformation, at least one grid missing unknown id, Transformation from NGVD29 height (ftUS) to NAVD88 height (ballpark vertical transformation) + NAD27 to NAD83 (9), unknown accuracy, Canada - Saskatchewan, has ballpark transformation, at least one grid missing unknown id, Transformation from NGVD29 height (ftUS) to NAVD88 height (ballpark vertical transformation) + Ballpark geographic offset from NAD27 to NAD83, unknown accuracy, World, has ballpark transformation
否则,当没有这种转换时,我们分解为3个步骤:
从源CRS转换到与其对应的地理3D CRS
从源CR对应的地理3D CR转换为目标CR对应的地理3D CR
从对应于目标CRS的地理3D CRS到目标CRS的变换。
例子:
$ projinfo -s "WGS 84 + EGM96 height" -t "ETRS89 + Belfast height" --spatial-test intersects --summary Candidate operations found: 7 unknown id, Inverse of WGS 84 to EGM96 height (1) + Inverse of ETRS89 to WGS 84 (1) + ETRS89 to Belfast height (2), 2.014 m, UK - Northern Ireland - onshore unknown id, Inverse of WGS 84 to EGM96 height (1) + Inverse of ETRS89 to WGS 84 (1) + ETRS89 to Belfast height (1), 2.03 m, UK - Northern Ireland - onshore, at least one grid missing unknown id, Inverse of WGS 84 to EGM96 height (1) + Null geographic offset from WGS 84 (geog3D) to WGS 84 (geog2D) + Inverse of OSGB 1936 to WGS 84 (4) + OSGB 1936 to ETRS89 (2) + Null geographic offset from ETRS89 (geog2D) to ETRS89 (geog3D) + ETRS89 to Belfast height (2), 19.044 m, unknown domain of validity unknown id, Inverse of WGS 84 to EGM96 height (1) + Null geographic offset from WGS 84 (geog3D) to WGS 84 (geog2D) + Inverse of OSGB 1936 to WGS 84 (2) + OSGB 1936 to ETRS89 (2) + Null geographic offset from ETRS89 (geog2D) to ETRS89 (geog3D) + ETRS89 to Belfast height (2), 11.044 m, unknown domain of validity unknown id, Inverse of WGS 84 to EGM96 height (1) + Null geographic offset from WGS 84 (geog3D) to WGS 84 (geog2D) + Inverse of TM75 to WGS 84 (2) + TM75 to ETRS89 (3) + Null geographic offset from ETRS89 (geog2D) to ETRS89 (geog3D) + ETRS89 to Belfast height (2), 2.424 m, UK - Northern Ireland - onshore, at least one grid missing unknown id, Inverse of WGS 84 to EGM96 height (1) + Null geographic offset from WGS 84 (geog3D) to WGS 84 (geog2D) + Inverse of TM75 to WGS 84 (2) + TM75 to ETRS89 (3) + Null geographic offset from ETRS89 (geog2D) to ETRS89 (geog3D) + ETRS89 to Belfast height (1), 2.44 m, UK - Northern Ireland - onshore, at least one grid missing unknown id, Inverse of WGS 84 to EGM96 height (1) + Null geographic offset from WGS 84 (geog3D) to WGS 84 (geog2D) + Inverse of OSGB 1936 to WGS 84 (4) + OSGB 1936 to ETRS89 (2) + Null geographic offset from ETRS89 (geog2D) to ETRS89 (geog3D) + ETRS89 to Belfast height (1), 19.06 m, unknown domain of validity, at least one grid missing
这是由 createOperationsCompoundToCompound
方法
当源CRS或目标CRS是边界CRS时¶
BoundCRS概念是一个混合概念,其中CRS链接到从它到中心CRS的转换,通常是WGS 84。这是一个长期的实践项目。4字符串与 +towgs84
, +nadgrids
和 +geoidgrids
关键字,或 TOWGS84[]
WKT 1的节点。当解析CRS字符串时遇到这些属性时,PROJ将创建一个BoundCRS对象来捕获这个转换。BoundCRS对象还可以提供WKT2字符串,在这种情况下,hub CRS可能不同于WGS 84。
让我们考虑一下边界CRS(“+proj=tmerc+lat_0=49+lon_0=-2+k=0.999612717+x_0=400000+y_0=-100000+ellps=airy+towgs84=446.448,-125.157542.06,0.15,0.247,0.842,-20.489+units=m”这曾经是“OSGB 1936/英国国家电网”的项目4定义)和目标地理CRS ETRS89之间的转换。
我们采用以下步骤:
从源CRS的基部(即由BoundCRS包装的CRS,这里是ProjectedCRS)转换到这个基部CRS的地理CRS
应用BoundCRS的变换,从该基本CRS的地理CRS到BoundCRS的中心CRS,在该实例中为WGS 84。
应用从中心CRS到目标CRS的变换。
这是由 createOperationsBoundToGeog
方法
例子:
$ projinfo -s "+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +towgs84=446.448,-125.157,542.06,0.15,0.247,0.842,-20.489 +units=m +type=crs" -t ETRS89 -o PROJ
Candidate operations found: 1
-------------------------------------
Operation No. 1:
unknown id, Inverse of unknown + Transformation from unknown to WGS84 + Inverse of ETRS89 to WGS 84 (1), unknown accuracy, Europe - ETRS89
PROJ string:
+proj=pipeline +step +inv +proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +step +proj=push +v_3 +step +proj=cart +ellps=airy +step +proj=helmert +x=446.448 +y=-125.157 +z=542.06 +rx=0.15 +ry=0.247 +rz=0.842 +s=-20.489 +convention=position_vector +step +inv +proj=cart +ellps=GRS80 +step +proj=pop +v_3 +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1
BoundCRS还有其他情况,包括垂直转换,或者转换到地理CRS以外的其他对象,但是好奇的读者必须检查代码中实际的血淋淋的细节。