项目RFC 2:“GDAL SRS barn”工作的初步整合

作者

甚至鲁奥

联系

即使是鲁奥在空间分析网站

状态

在项目6.0中采用并实施

初始版本

2018-10-09

最后更新

2018-10-31

总结

此RFC是 GDAL Coordinate System Barn Raising 努力。目前,这项工作主要包括:

  • 一个C++实现的ISO-19111:2018/OGC主题2“坐标引用”类来表示Datums、坐标系、CRSs(坐标参考系)和坐标操作。

  • 方法在C++建模和WKT1、WKT2和PROJ字符串表示之间进行转换

  • CRS的SQLite3数据库管理与查询及协同操作定义

  • C API绑定是这些功能的一部分

细节

包/名称空间中的结构

即将到来的ISO-19111:2018/OGC主题2的C++实现(参考坐标)类尽可能地使用这个抽象的模型,使用包名称作为C++命名空间、抽象类和方法名。添加了一个新的BoundCRS类来覆盖WKT2 BoundCRS构造的建模,这是WKT1 TOWGS84概念的推广。强烈建议打开ISO-19111标准,以便在查看代码时对概念进行介绍。一些类也受到GeoAPI的启发

这些类被组织成几个名称空间:

  • osgeo::项目::工具

    来自iso19103、GeoAPI和其他项目“技术”特定类的一组基类型

    模板可选<T>,classes BaseObject,IComparable,BoxedValue,ArrayOfBaseObject,PropertyMap,LocalName,NameSpace,GenericName,NameFactory,CodeList,Exception,InvalidValueTypeException,UnsupportedOperationException

  • osgeo::proj::元数据:

    ISO 19115(元数据)标准中的公共类

    类引用,地理范围,地理边界框,时间内容,垂直范围,范围,标识符,位置精度,

  • osgeo::项目::公用:

    公共类:UnitOfMeasure、Measure、Scale、Angle、Length、DateTime、DateEpoch、IdentifiedObject、ObjectDomain、ObjectUsage

  • osgeo::项目::cs:

    坐标系及其轴

    类轴方向、子午线、坐标系轴、坐标系、球体、椭球体、垂直、笛卡尔、序数、参数、时间、日期时间、时间计数、时间测量

  • osgeo::项目::基准:

    基准(坐标系与物体的关系)

    类椭球、本初子午线、基准、基准符号、大地测量基准框架、动态大地测量基准框架、垂直基准框架、动态垂直基准框架、临时基准、工程基准、参数基准

  • osgeo::项目::crs:

    CRS=坐标参考系=带基准的坐标系

    类别CRS、大地测量CRS、地理CCR、衍生CRS、投影CRS、垂直CRS、复合CRS、边界CRS、临时CRS、工程CRS、参数CRS、衍生大地测量CRS、衍生地理CCR、衍生投影CRS、衍生垂直CRS

  • osgeo::proj::操作:

    坐标操作(任意两个坐标参考系之间的关系)

    类CoordinateOperation、GeneralOperationParameter、OperationParameter、GeneralParameterValue、ParameterValue、OperationParameterValue、OperationMethod、InvalidOperation、SingleOperation、Conversion、Transformation、PointMotionOperation、ConcatenatedOperation

  • osgeo::项目::io:

    I/O类:WKTFormatter、PROJStringFormatter、FormattingException、parsingeexception、IWKTExportable、IPROJStringExportable、WKTNode、WKTParser、PROJStringParser、DatabaseContext、AuthorityFactory、FactoryException、NoSuchAuthorityCodeException

什么是什么?

解析WKT和PROJ字符串以及构建ISO-19111对象的代码包含在 io.cpp

格式化ISO-19111对象中WKT和PROJ字符串的代码主要包含在相关的exportToWKT()和exportToPROJString()方法中,这些方法在适用的类中被重写。 io.cpp 包含构造此类弦的一般机制。

关于WKT字符串,在导入和导出中处理三种变体:

  • WKT2U 2018:与即将发布的ISO-19162:2018标准相对应的变体

  • WKT2U 2015:与现行ISO-19162:2015标准相对应的变体

  • WKT1U GDAL:与GDAL理解OGC 01-099和OGC 99-049标准的方式相对应的变体

关于项目字符串,在导入和导出中处理两个变量:

  • PROJ5:PROJ>=5使用的变量,可能使用管道构造,避免使用+towgs84/+nadgrids遗留构造。此变体尊重轴顺序和输入/输出单位。这就是转化的管道EPSG:4326至EPSG:32631将假设输入坐标是纬度、经度和度数的顺序。

  • PROJ4:PROJ4.x使用的变量

的原始查询项目数据库并从数据库内容中进行ISO-19111对象的上层构造 factory.cpp

几个设计原则

方法通常接受并返回xxxNNPtr对象,即非空共享指针(具有内部引用计数的指针)。这种方法的优点是用户不必关心实例的生命周期(这使得代码在设计上是无泄漏的)。唯一要注意的是确保没有参考周期。这是所有类的情况,除了指向源CRS和目标CRS成员的CRS的协调操作类,而派生的CRS指向转换实例(派生自协调操作)。在ISO-19111标准中检测到了该问题。这里采用的解决方案是在协调操作类中使用std::ware_ptr来避免循环。这种设计艺术品对用户来说是透明的。

另一个重要的设计点是,所有ISO19111对象在创建后都是不可变的,即它们只有不修改其状态的getter。因此,它们可能以线程安全的方式使用。但是,有些类,如PROJStringFormatter、WKTFormatter、DatabaseContext、AuthorityFactory和CoordinateOperationContext,它们的实例是可变的,因此不能同时被多个线程使用。

示例如何构建EPSG:4326/WGS84从头定义:

auto greenwich = PrimeMeridian::create(
    util::PropertyMap()
        .set(metadata::Identifier::CODESPACE_KEY,
            metadata::Identifier::EPSG)
        .set(metadata::Identifier::CODE_KEY, 8901)
        .set(common::IdentifiedObject::NAME_KEY, "Greenwich"),
    common::Angle(0));
// actually predefined as PrimeMeridian::GREENWICH constant

auto ellipsoid = Ellipsoid::createFlattenedSphere(
    util::PropertyMap()
        .set(metadata::Identifier::CODESPACE_KEY, metadata::Identifier::EPSG)
        .set(metadata::Identifier::CODE_KEY, 7030)
        .set(common::IdentifiedObject::NAME_KEY, "WGS 84"),
    common::Length(6378137),
    common::Scale(298.257223563));
// actually predefined as Ellipsoid::WGS84 constant

auto datum = GeodeticReferenceFrame::create(
    util::PropertyMap()
        .set(metadata::Identifier::CODESPACE_KEY, metadata::Identifier::EPSG)
        .set(metadata::Identifier::CODE_KEY, 6326)
        .set(common::IdentifiedObject::NAME_KEY, "World Geodetic System 1984");
    ellipsoid
    util::optional<std::string>(), // anchor
    greenwich);
// actually predefined as GeodeticReferenceFrame::EPSG_6326 constant

auto geogCRS = GeographicCRS::create(
    util::PropertyMap()
        .set(metadata::Identifier::CODESPACE_KEY, metadata::Identifier::EPSG)
        .set(metadata::Identifier::CODE_KEY, 4326)
        .set(common::IdentifiedObject::NAME_KEY, "WGS 84"),
    datum,
    cs::EllipsoidalCS::createLatitudeLongitude(scommon::UnitOfMeasure::DEGREE));
// actually predefined as GeographicCRS::EPSG_4326 constant

算法焦点

在算法方面,一个稍微复杂的逻辑是中的CoordinateOperationFactory::createOperations() coordinateoperation.cpp 它获取一对源和目标CR并返回一组可能的 coordinate operations (可以是像转换或转换这样的单一操作,也可以是串联操作)。它使用这些对象的内部结构来创建坐标操作管道。也就是说,如果从一个ProjectedCRS转到另一个,则首先执行从源ProjectedCRS到其基本地理CRS的逆转换,然后找到从该基本地理CRS到目标CRS的基本地理CRS的适当变换,然后将从该基本地理CRS的转换应用到目标ProjectedCRS。在每个步骤中,它都会查询数据库,以确定是否有一个或多个转换可用。根据用户提供的提示,对生成的坐标操作进行过滤和排序:

  • 期望精度

  • 使用区域,定义为经纬度空间中的边界框(其实际CRS与预期用途无关)

  • 如果未定义使用区域,则应使用源和目标CR的使用区域以及如何使用。默认情况下,使用最小的使用区域。例如,当在国家计划的CRS和世界范围的CCR之间转换时,使用这些计划的CRS来选择适当的基准偏移。

  • 如何比较候选转换的使用区域和所需的使用区域(如上所述,显式或隐式定义)。默认情况下,仅选择使用区域完全包含在所需使用区域中的变换。也可以通过指定仅必须使用交集测试来放宽此测试。

  • 是否 PROJ transformation grid 名称应替换为正式名称,如果在 grid_alternatives 数据库的表。缺省为True

  • 是否应该使用这些网格的可用性来过滤和排序结果。默认情况下,将首先显示使用系统中可用网格的变换。

对结果进行排序,最相关的结果首先出现在结果向量中。使用的标准是按顺序排列的

  • 网格实际可用性:引用网格不可用的操作将列在具有可用网格的操作之后

  • 网格潜在可用性:操作引用的网格在数据库中根本不知道项目数据库将在已知网格但不可用的操作之后列出。

  • 已知精度:在已知精度的操作之后,将列出未知精度的操作

  • 使用面积:使用面积较小的操作(使用的操作面积与所需使用面积的交点)将列在使用面积较大的操作之后

  • 精度:精度较低的操作将在精度较高的操作之后列出(注意:精度较低实际上意味着精度属性的数值较高,因为它是以米为单位的精度)

所有这些设置都可以在传递给createOperations()的CoordinateOperationContext实例中指定。

一个有趣的例子是使用 projinfo -s EPSG:4267 -t EPSG:4326 (NAD27到WGS84的转换),并查看指定所需的使用区域、空间标准、网格可用性等对结果的影响。

以下命令当前返回78个结果:

projinfo -s EPSG:4267 -t EPSG:4326 --summary --spatial-test intersects

createOperations()算法还执行一种“CRS路由”。一个典型的例子是,如果想要在CRS A和CRS B之间进行转换,但是中没有引用直接转换项目数据库在这两者之间。但是,如果A<-->C和B<-->C之间存在转换,则可以构建串联操作A-->C-->B。典型的示例是C是WGS84,但实现是通用的,只是从数据库中找到一个公共轴。查找非WGS84轴的示例是在EPSG:4326和EPSG:6668(JGD2011-日本大地基准2011),在EPSG数据库中没有注册直接转换。然而,这两个CRS和JGD2000之间存在转换(还有东京数据,但这一个涉及的转换精度较低)

projinfo -s EPSG:4326 -t EPSG:6668  --grid-check none --bbox 135.42,34.84,142.14,41.58 --summary

Candidate operations found: 7
unknown id, Inverse of JGD2000 to WGS 84 (1) + JGD2000 to JGD2011 (1), 1.2 m, Japan - northern Honshu
unknown id, Inverse of JGD2000 to WGS 84 (1) + JGD2000 to JGD2011 (2), 2 m, Japan excluding northern main province
unknown id, Inverse of Tokyo to WGS 84 (108) + Tokyo to JGD2011 (2), 9.2 m, Japan onshore excluding northern main province
unknown id, Inverse of Tokyo to WGS 84 (108) + Tokyo to JGD2000 (2) + JGD2000 to JGD2011 (1), 9.4 m, Japan - northern Honshu
unknown id, Inverse of Tokyo to WGS 84 (2) + Tokyo to JGD2011 (2), 13.2 m, Japan - onshore mainland and adjacent islands
unknown id, Inverse of Tokyo to WGS 84 (2) + Tokyo to JGD2000 (2) + JGD2000 to JGD2011 (1), 13.4 m, Japan - northern Honshu
unknown id, Inverse of Tokyo to WGS 84 (1) + Tokyo to JGD2011 (2), 29.2 m, Asia - Japan and South Korea

代码库

工作的当前状态可以在 iso19111 branch of rouault/proj.4 repository ,也可以作为GitHub pull请求在https://github.com/OSGeo/proj.4/pull/1040

这是一个不太实用的 comparison with a fixed snapshot of master branch

数据库

内容

数据库包含来自 EPSG 数据库(IOGP的EPSG大地测量参数数据集)v9.5.3, IGNF registry (法国国家地理研究所),ESRI数据库,以及一些定制。

构建(用于项目开发人员创建数据库)

数据库的建立分为几个阶段:

为EPSG构造SQL脚本

第一阶段是构造.sql脚本,主要使用CREATE TABLE和INSERT语句来创建数据库结构并填充它。每个数据库表都有一个.sql文件,该文件由EPSG数据库的内容填充,并由 build_db.py 脚本,它处理IOGP发出的PostgreSQL转储。例如,许多其他脚本专用于手动编辑 grid_alternatives.sql 将正式网格名称绑定到项目网格名称的文件

协调UTF8 SQL到sqlite3 db

第二阶段由make过程自动完成。它以正确的顺序将.sql脚本传输到sqlite3二进制文件,以生成项目数据库SQLite3数据库。

添加额外的注册表

第三个阶段是从其他注册表的内容创建额外的.sql文件。对于这个过程,我们需要将这些注册表的一些定义绑定到EPSG数据库的定义,以便能够链接到现有对象并检测一些无聊的重复项。这个 ignf.sql 文件已使用 build_db_create_ignf.py 来自当前data/IGNF文件的脚本,该文件包含CRS定义(以及对WGS84的隐式转换)作为PROJ.4字符串。这个 esri.sql 文件已使用 build_db_from_esri.py 脚本,来自中的.csv文件https://github.com/Esri/projection-engine-db-doc/tree/master/csv

定稿项目数据库

最后一个阶段再次运行make以合并在前一个阶段中生成的新.sql文件(因此构建数据库的过程涉及一种引导…)

建筑(项目用户)

make进程只是从.sql文件运行上面提到的第二个阶段。结果项目数据库当前为5.3 MB。

结构

数据库的结构如下表和视图所示。它们通常符合ISO-19111的概念,并且通常接近EPSG数据库的一般结构。关于对象的标识,在EPSG数据库中只包含一个“code”数字列,PROJ数据库用字符串值的(authu name,code)元组标识对象,允许将多个注册表组合在一起。

  • 技术:
    • authority_list :枚举数据库中存在的权限的视图。目前:EPSG、IGNF、PROJ

    • metadata :一些键/值对,例如用于指示数据库中导入的注册表的版本

    • object_view :综合视图列出对象(椭球体、基准、CR、坐标操作…)代码和名称,以及进一步描述它们的表名

    • alias_names :列出可能的别名 name 对象表字段

    • link_from_deprecated_to_non_deprecated :处理旧ESRI与新ESRI/EPSG代码之间的链接

  • 普通:
    • unit_of_measure :带有度量单位定义的表。

    • area :带有适用于CRS和坐标操作的使用区域(边界框)的表格。

  • 坐标系:
    • axis :带有坐标系定义的表。

    • coordinate_system :带有坐标系定义的表。

  • 椭球体和基准面:
    • ellipsoid :具有椭球体定义的表。

    • prime_meridian :包含PrimeMeridian定义的表。

    • geodetic_datum :带有大地测量参考帧定义的表。

    • vertical_datum :具有VerticalReferenceFrame定义的表。

  • CRS公司:
    • geodetic_crs :带有大地测量CR和地理CCRS定义的表格。

    • projected_crs :带有ProjectedCRS定义的表。

    • vertical_crs :带有垂直CRS定义的表。

    • compound_crs :带有复合词定义的表。

  • 协调操作:
    • coordinate_operation_view :视图,给出实现协调操作的具体表共享的多个公共属性

    • conversion :带有转换定义的表(主要是参数和投影值)

    • concatenated_operation :带有ConcatenatedOperation定义的表。

    • grid_transformation :包含所有基于网格的转换的表。

    • grid_packages :列出可在其中找到网格的包的表。例如“proj datumgrid”,“proj datumgrid europe”。。。

    • grid_alternatives :将正式网格名称绑定到项目网格名称的表。e、 g“Und u min2.5x2.5英寸egm2008英寸isw=82英寸WGS84英寸_提德弗里.gz“-->”egm08U 25.gtx“

    • helmert_transformation :包含所有基于Helmert的转换的表。

    • other_transformation :包含其他类型转换的表。

EPSG数据库结构的主要区别是将各种坐标操作拆分到多个表上。这样做主要是为了提高可读性,因为coordoperation、coordoperationmethod、coordoperationparam、coordoperationparamusause、coordoperationparamvalue表的EPSG组织使得很难同时掌握给定操作的所有参数和值。

公用事业

一个新的 projinfo 已添加实用程序。它使用户能够通过权限:代码,PROJ string或WKT string,并查看它在不同风格的PROJ和WKT字符串中的翻译。它还可以在两个crs之间建立协调操作。

使用

usage: projinfo [-o formats] [-k crs|operation] [--summary] [-q]
                [--bbox min_long,min_lat,max_long,max_lat]
                [--spatial-test contains|intersects]
                [--crs-extent-use none|both|intersection|smallest]
                [--grid-check none|discard_missing|sort]
                [--boundcrs-to-wgs84]
                {object_definition} | (-s {srs_def} -t {srs_def})

-o: formats is a comma separated combination of: all,default,PROJ4,PROJ,WKT_ALL,WKT2_2015,WKT2_2018,WKT1_GDAL
    Except 'all' and 'default', other format can be preceded by '-' to disable them

实例

指定CRS依据权限:代码

$ projinfo EPSG:4326

PROJ string:
+proj=pipeline +step +proj=longlat +ellps=WGS84 +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1

WKT2_2015 string:
GEODCRS["WGS 84",
    DATUM["World Geodetic System 1984",
        ELLIPSOID["WGS 84",6378137,298.257223563,
            LENGTHUNIT["metre",1]]],
    PRIMEM["Greenwich",0,
        ANGLEUNIT["degree",0.0174532925199433]],
    CS[ellipsoidal,2],
        AXIS["geodetic latitude (Lat)",north,
            ORDER[1],
            ANGLEUNIT["degree",0.0174532925199433]],
        AXIS["geodetic longitude (Lon)",east,
            ORDER[2],
            ANGLEUNIT["degree",0.0174532925199433]],
    AREA["World"],
    BBOX[-90,-180,90,180],
    ID["EPSG",4326]]

按项目字符串指定CRS并指定输出格式

$ projinfo -o PROJ4,PROJ,WKT1_GDAL,WKT2_2018 "+title=IGN 1972 Nuku Hiva - UTM fuseau 7 Sud +proj=tmerc +towgs84=165.7320,216.7200,180.5050,-0.6434,-0.4512,-0.0791,7.420400 +a=6378388.0000 +rf=297.0000000000000 +lat_0=0.000000000 +lon_0=-141.000000000 +k_0=0.99960000 +x_0=500000.000 +y_0=10000000.000 +units=m +no_defs"

PROJ string:
Error when exporting to PROJ string: BoundCRS cannot be exported as a PROJ.5 string, but its baseCRS might

PROJ.4 string:
+proj=utm +zone=7 +south +ellps=intl +towgs84=165.732,216.72,180.505,-0.6434,-0.4512,-0.0791,7.4204

WKT2_2018 string:
BOUNDCRS[
    SOURCECRS[
        PROJCRS["IGN 1972 Nuku Hiva - UTM fuseau 7 Sud",
            BASEGEOGCRS["unknown",
                DATUM["unknown",
                    ELLIPSOID["International 1909 (Hayford)",6378388,297,
                        LENGTHUNIT["metre",1,
                            ID["EPSG",9001]]]],
                PRIMEM["Greenwich",0,
                    ANGLEUNIT["degree",0.0174532925199433],
                    ID["EPSG",8901]]],
            CONVERSION["unknown",
                METHOD["Transverse Mercator",
                    ID["EPSG",9807]],
                PARAMETER["Latitude of natural origin",0,
                    ANGLEUNIT["degree",0.0174532925199433],
                    ID["EPSG",8801]],
                PARAMETER["Longitude of natural origin",-141,
                    ANGLEUNIT["degree",0.0174532925199433],
                    ID["EPSG",8802]],
                PARAMETER["Scale factor at natural origin",0.9996,
                    SCALEUNIT["unity",1],
                    ID["EPSG",8805]],
                PARAMETER["False easting",500000,
                    LENGTHUNIT["metre",1],
                    ID["EPSG",8806]],
                PARAMETER["False northing",10000000,
                    LENGTHUNIT["metre",1],
                    ID["EPSG",8807]]],
            CS[Cartesian,2],
                AXIS["(E)",east,
                    ORDER[1],
                    LENGTHUNIT["metre",1,
                        ID["EPSG",9001]]],
                AXIS["(N)",north,
                    ORDER[2],
                    LENGTHUNIT["metre",1,
                        ID["EPSG",9001]]]]],
    TARGETCRS[
        GEOGCRS["WGS 84",
            DATUM["World Geodetic System 1984",
                ELLIPSOID["WGS 84",6378137,298.257223563,
                    LENGTHUNIT["metre",1]]],
            PRIMEM["Greenwich",0,
                ANGLEUNIT["degree",0.0174532925199433]],
            CS[ellipsoidal,2],
                AXIS["latitude",north,
                    ORDER[1],
                    ANGLEUNIT["degree",0.0174532925199433]],
                AXIS["longitude",east,
                    ORDER[2],
                    ANGLEUNIT["degree",0.0174532925199433]],
            ID["EPSG",4326]]],
    ABRIDGEDTRANSFORMATION["Transformation from unknown to WGS84",
        METHOD["Position Vector transformation (geog2D domain)",
            ID["EPSG",9606]],
        PARAMETER["X-axis translation",165.732,
            ID["EPSG",8605]],
        PARAMETER["Y-axis translation",216.72,
            ID["EPSG",8606]],
        PARAMETER["Z-axis translation",180.505,
            ID["EPSG",8607]],
        PARAMETER["X-axis rotation",-0.6434,
            ID["EPSG",8608]],
        PARAMETER["Y-axis rotation",-0.4512,
            ID["EPSG",8609]],
        PARAMETER["Z-axis rotation",-0.0791,
            ID["EPSG",8610]],
        PARAMETER["Scale difference",1.0000074204,
            ID["EPSG",8611]]]]

WKT1_GDAL:
PROJCS["IGN 1972 Nuku Hiva - UTM fuseau 7 Sud",
    GEOGCS["unknown",
        DATUM["unknown",
            SPHEROID["International 1909 (Hayford)",6378388,297],
            TOWGS84[165.732,216.72,180.505,-0.6434,-0.4512,-0.0791,7.4204]],
        PRIMEM["Greenwich",0,
            AUTHORITY["EPSG","8901"]],
        UNIT["degree",0.0174532925199433,
            AUTHORITY["EPSG","9122"]],
        AXIS["Longitude",EAST],
        AXIS["Latitude",NORTH]],
    PROJECTION["Transverse_Mercator"],
    PARAMETER["latitude_of_origin",0],
    PARAMETER["central_meridian",-141],
    PARAMETER["scale_factor",0.9996],
    PARAMETER["false_easting",500000],
    PARAMETER["false_northing",10000000],
    UNIT["metre",1,
        AUTHORITY["EPSG","9001"]],
    AXIS["Easting",EAST],
    AXIS["Northing",NORTH]]

查找两个CR之间的变换

“波兰I区”(基于Pulkovo 42基准)和“UTM WGS84 34N区”之间

摘要视图:

$ projinfo -s EPSG:2171 -t EPSG:32634 --summary

Candidate operations found: 1
unknown id, Inverse of Poland zone I + Pulkovo 1942(58) to WGS 84 (1) + UTM zone 34N, 1 m, Poland - onshore

管线显示:

$ PROJ_LIB=data src/projinfo -s EPSG:2171 -t EPSG:32634 -o PROJ

PROJ string:
+proj=pipeline +step +proj=axisswap +order=2,1 +step +inv +proj=sterea +lat_0=50.625 +lon_0=21.0833333333333 +k=0.9998 +x_0=4637000 +y_0=5647000 +ellps=krass +step +proj=cart +ellps=krass +step +proj=helmert +x=33.4 +y=-146.6 +z=-76.3 +rx=-0.359 +ry=-0.053 +rz=0.844 +s=-0.84 +convention=position_vector +step +inv +proj=cart +ellps=WGS84 +step +proj=utm +zone=34 +ellps=WGS84

受影响的文件

新文件(不包括MakeFile.am、CMakeLists.txt和其他构建基础设施人工制品):

  • 包含/PRJ/:公共安装的C++标题
    • common.hpp: osgeo::proj::common命名空间的声明。

    • coordinateoperation.hpp: osgeo::proj::operation命名空间的声明。

    • coordinatesystem.hpp: osgeo::proj::cs命名空间的声明。

    • crs.hpp: osgeo::proj::crs命名空间的声明。

    • datum.hpp: osgeo::proj::datum命名空间的声明。

    • io.hpp: osgeo::proj::io命名空间的声明。

    • metadata.hpp: osgeo::proj::metadata命名空间的声明。

    • util.hpp: osgeo::proj::util命名空间的声明。

    • nn.hpp: 代码来自https://github.com/dropbox/nn管理C++中的不可空指针

计算机辅助编程接口

proj.h 已经扩展到将多个C++类/方法绑定到一个C API。

主体结构是一个不透明的PJïU对象 * roughly encapsulating a osgeo::proj::BaseObject, that can represent a CRS or a CoordinateOperation object. A number of the C functions will work only if the right type of underlying C++ object is used with them. Misuse will be properly handled at runtime. If a user passes a PJ_OBJ* 将坐标操作表示为pju obju crsu xxxx()函数,它将正确地出错。这种设计已经被选择为每个C++类创建一个专用的PJYXXX对象,因为这样的方法需要增加很多转换和自由函数,但却没有什么好处。

此C API不完整。在手上,它不允许特殊对象。然而,它目前允许一些行动:

  • 从WKT和PROJ字符串或从项目数据库数据库

  • 将CRS和协调操作导出为WKT和项目字符串

  • 查询这些主要对象的属性

  • 寻找两个CR之间的坐标运算。

test_c_api.cpp 应该演示API的简单用法(注意:为了方便在C++中编写测试,TestJoCI)api.cpp公司将C++ PJOBOR**实例封装在函数结束时自动调用PJAObjununFor()函数的C++守护程序对象中。在纯C语言中,调用者必须使用pju obju unref()来防止泄漏。)

文档

所有的C++类和方法和C函数都是用DoXEGEN记录的。

Current snapshot of Class list

Spaghetti inheritance diagram

已经使用Sphinx扩展完成了将DOOXO XML输出集成到常规项目文档中的基本工作(使用reStruredText格式 Breathe ,制作:

测试

几乎所有导出的方法都通过单元测试进行测试。新文件的全局行覆盖率为92%。这些测试代表了16k行代码。

生成要求

新代码利用了许多C++ 11个特性(AutoToC、CONTXPR、初始化列表、STD::SyrdY-PTR、lambda函数等),这意味着必须使用C++ 11兼容编译器来生成PROJ:

  • 合同通用条款>=4.8

  • 叮当声>=3.3

  • Visual Studio>=2015年。

由Travis CI和AppVeyor持续集成环境测试的编译器:

  • 通用条款8.4

  • 8-w64-x86宽

  • 叮当声5.0

  • Apple LLVM版本9.1.0(clang-902.0.39.2)

  • MSVC 2015 32位和64位

  • MSVC 2017 32位和64位

libsqlite3>=3.7开发包也必须可用。并且sqlite3二进制文件必须可用于构建项目数据库来自.sql文件的文件。

运行时要求

  • libc++/libstdc++/MSVC运行时与使用的编译器一致

  • libsqlite3>=3.7

向后兼容性

在这个阶段,没有向后兼容性的问题是可以预见的,因为没有现有的功能C代码被修改以使用新的功能

今后的工作

本RFC中描述的工作将在多个方向上进行。非穷尽性地:

  • 支持ESRI WKT1方言(项目当前接收中的ProjectedCRS) esri.sql 但它与EPSG操作和参数名之间没有映射,因此转换为PROJ字符串并不总是有效的。

  • 与现有代码库的更紧密集成。尤其是+init=dict:代码语法现在应该首先转到数据库(然后是 epsgIGNF 可以删除文件)。类似地,proju create u crs u to u crs()可以使用新的功能找到适当的坐标变换。

  • 为了满足GDAL和libgeotiff的需求,还需要做其他任何改变

收养状况

RFC得到了PSC成员Kurt Schwehr、Kristian Evers、Howard Butler甚至Rouault的支持。