RFC 61:测量几何图形的支持

作者:Ari Jolma

联系人:ari.jolma,gmail.com

状态:通过

版本实现:2.1

总结

此RFC定义了如何实现测量的几何图形(几何图形,其中点具有M坐标,即它们是XYM或XYZM)。

理论基础

M坐标,也称为“测量”,是可以为几何图形的每个点存储的附加值(IBM技术说明, https://www-304.ibm.com/support/docview.wss?uid=swg21054384

M坐标在OGC简单特征模型中,它被用于多种矢量数据格式。

变化

在C++ API中需要进行更改,需要增强C API。一些驱动程序需要改变以利用这种增强,但也由于C++ API的改变。

通用API

需要新的OGRwkbGeometryType值。将使用SFSQL 1.2和ISO SQL/MM第3部分,即M为2D类型+2000,ZM为2D类型+3000。(也可以添加类型,如Tin、多面体曲面和三角形类型以获得完整性,即使当前未实现)。wkbCurve和wkbSurface已从“define”移到“OGRwkbGeometryType”枚举,并添加了它们的Z/M/ZM变体(根据6401)

总的来说,有可能(应该?)成为使用一组干净值的路径,并将遗留支持作为异常。

抽象类型是定义的,而不是枚举的一部分。

// additions to enum OGRwkbGeometryType
    wkbCurve = 13,          /**< Curve (abstract type). ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbSurface = 14,        /**< Surface (abstract type). ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbPolyhedralSurface = 15,/**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbTIN = 16,              /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbTriangle = 17,         /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */

    wkbCurveZ = 1013,           /**< wkbCurve with Z component. ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbSurfaceZ = 1014,         /**< wkbSurface with Z component. ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbPolyhedralSurfaceZ = 1015,  /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbTINZ = 1016,                /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbTriangleZ = 1017,           /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */

    wkbPointM = 2001,              /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbLineStringM = 2002,         /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbPolygonM = 2003,            /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbMultiPointM = 2004,         /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbMultiLineStringM = 2005,    /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbMultiPolygonM = 2006,       /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbGeometryCollectionM = 2007, /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbCircularStringM = 2008,     /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbCompoundCurveM = 2009,      /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbCurvePolygonM = 2010,       /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbMultiCurveM = 2011,         /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbMultiSurfaceM = 2012,       /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbCurveM = 2013,              /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbSurfaceM = 2014,            /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbPolyhedralSurfaceM = 2015,  /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbTINM = 2016,                /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbTriangleM = 2017,           /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */

    wkbPointZM = 3001,              /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbLineStringZM = 3002,         /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbPolygonZM = 3003,            /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbMultiPointZM = 3004,         /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbMultiLineStringZM = 3005,    /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbMultiPolygonZM = 3006,       /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbGeometryCollectionZM = 3007, /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbCircularStringZM = 3008,     /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbCompoundCurveZM = 3009,      /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbCurvePolygonZM = 3010,       /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbMultiCurveZM = 3011,         /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbMultiSurfaceZM = 3012,       /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbCurveZM = 3013,              /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbSurfaceZM = 3014,            /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbPolyhedralSurfaceZM = 3015,  /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbTINZM = 3016,                /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */
    wkbTriangleZM = 3017,           /**< ISO SQL/MM Part 3. GDAL &gt;= 2.1 */

// add tests for M
#define wkbHasM(x)     OGR_GT_HasM(x)
#define wkbSetM(x)     OGR_GT_SetM(x)

OGRwkbGeometryType CPL_DLL OGR_GT_SetM( OGRwkbGeometryType eType );
int                CPL_DLL OGR_GT_HasM( OGRwkbGeometryType eType );

C++ API

类OGRGeometry中的属性int ncordinatedimmension将被int flags替换。它可能有以下标志:

#define OGR_G_NOT_EMPTY_POINT 0x1
#define OGR_G_3D 0x2
#define OGR_G_MEASURED 0x4
#define OGR_G_IGNORE_MEASURED 0x8

为了向后兼容,内部需要使用“ignore”标志。标志OGR_G_NOT_EMPTY_POINT仅用于表示OGRPoint对象的空性。

目前,设置nCoordDimension负数的技巧用于表示一个空点。

删除不协调维度可能意味着获取或设置它的驱动程序等发生更改。

测试是

Is3D = flags & OGR_G_3D
IsMeasured = flags & OGR_G_MEASURED

setter和getter是用|=和&=实现的。

当这些标志中的任何一个被设置或取消设置时,相应的数据将无效并可能被丢弃。

保留以下具有原始语义的方法,即坐标维为2或3,但不推荐。文件中有一些不符之处。他们的文档说,在ogrpoint.cpp中,空点可能返回零,而在ogrpoint.cpp中,空点使用负nCoordDimension值,点的getcoorderedimension方法返回nCoordDimension的绝对值,因此不是零。医生的治疗也许就足够了。

int getCoordinateDimension();
void setCoordinateDimension(int nDimension);
void flattenTo2D()

提出了一种新的方法来代替getCoordinateDimension。set3D和setMeasured将替换setCoordinateDimension并展平到2d。请参见下文。

类几何测量:

//Possibly add methods (SF Common Architecture):
int Dimension(); // -1 for empty geometries (to denote undefined), 0 for points, 1 for curves, 2 for surfaces, max of components for collections
char *GeometryType(); // calls OGRToOGCGeomType (which needs to be enhanced)

//Add methods (SF Common Architecture) see above for implementation:
int CoordinateDimension(); // 2 if not 3D and not measured, 3 if 3D or measured, 4 if 3D and measured
OGRBoolean Is3D() const;
OGRBoolean IsMeasured() const;

//Add methods (non-standard; note the use of one method instead of second unset* method):
virtual void set3D(OGRBoolean bIs3D);
virtual void setMeasured(OGRBoolean bIsMeasured);

//Add now or later methods:
virtual OGRGeometry *LocateAlong(double mValue);
virtual OGRGeometry *LocateBetween(double mStart, double mEnd);

//Remove b3D from importPreambleFromWkb: it is not used, the flags are managed within the method.

int CoordinateDimension()应该有新的语义。简单特征文档中的方法名实际上没有前缀get。

set3D和setMeasured是否应该影响集合中的子几何图形是一个问题。目前setCoordinateDimension的doc说“设置几何集合的维度将影响子几何图形”,因此我们已经承诺在集合中维护子几何图形的维度。建议set3D和setMeasured向几何体(包括可能的子对象)添加或删除Z或M值。一般来说,战略应遵循关于Z的现有战略(即删除或添加)。

将属性double m添加到类OGRPoint中。为它添加构造函数、getter和setter。

添加属性double * padfM到OGRSimpleCurve类。为它添加构造函数、getter和setter。XY M数据需要具有postfix M的新setter,因为在setters中对象可能从XY升级到XYZ。Add还使用与Make3D和Make2D具有类似语义的RemoveM()和AddM()方法。

在重写setCoordinatedDimension的类中重写方法set3D和setMeasured。

更改名称以开头的方法的语义 _ 并有一个参数“int b3D”。参数将是“int coordinates”,即一个类似int的标志,它表示Z和M。

计算机辅助编程接口

ogr_core.h:核心

OGRwkbGeometryType CPL_DLL OGR_GT_SetM( OGRwkbGeometryType eType );
int                CPL_DLL OGR_GT_HasM( OGRwkbGeometryType eType );

当前的行为是,对具有坐标尺寸2的几何体调用设定点会升级坐标尺寸3。为了保持2D点,必须使用2D设定点。因此,对于M和ZM几何,我们需要单独的函数。建议使用后缀M和ZM,即SetPointM和SetPointZM。AddPoint也一样。

目前没有设置点2 D功能。pabyZ param at SetPoints的doc注释为“对于2D对象默认为空”,但情况似乎并非如此。见#6344。如果按照这里写的那样修复,那么只需要SetPointsZM。

GetPoint和GetPoints没有2D版本,因此只有 * 需要ZM版本。

ogr_api.h:美国石油天然气协会

void   CPL_DLL OGR_G_Is3D( OGRGeometryH );
void   CPL_DLL OGR_G_IsMeasured( OGRGeometryH );

void   CPL_DLL OGR_G_Set3D( OGRGeometryH, int );
void   CPL_DLL OGR_G_SetMeasured( OGRGeometryH, int );

double CPL_DLL OGR_G_GetM( OGRGeometryH, int );

ogr_p.h(这是公共头,因此需要新函数)

const char CPL_DLL * OGRWktReadPointsM( const char * pszInput,
                                       OGRRawPoint **ppaoPoints,
                                       double **ppadfZ,
                                        double **ppadfM,
                                       int * pnMaxPoints,
                                       int * pnReadPoints );
void CPL_DLL OGRMakeWktCoordinateM( char *, double, double, double, double, int ); // int = flags OGR_G_3D OGR_G_MEASURED
// Change the semantics of OGRReadWKBGeometryType: b3D is not used and the returned eGeometryType may may any valid type

h是内部的,所以我们可以改变函数原型

void OGRCreateFromMultiPatchPart(OGRMultiPolygon *poMP,
                                 OGRPolygon*& poLastPoly,
                                 int nPartType,
                                 int nPartPoints,
                                 double* padfX,
                                 double* padfY,
                                 double* padfZ,
                                 double* padfM);

使用padfM需要更改openfilegdb驱动程序。

地理信息、过滤器和其他问题

将具有度量值的几何图形发送到GEOS或用作过滤器时,将忽略M坐标。

LocateAlong和LocateBetween是唯一的标准方法,它们使用M,但也可能有其他方法,例如获取M的范围。现在不打算添加这些方法,但以后可以添加它们。

SWIG绑定(Python/Java/C#/Perl)更改

新的C API函数需要通过swig公开。进一步的更改取决于语言绑定是否知道坐标。至少Python和Perl是。

新的几何图形类型将包含在i文件中。

需要为M.Is3D、IsMeasured、Set3D和SetMeasured方法添加一些新的setter和getter。同样的。

驱动程序

至少受C++更改影响的驱动程序至少是(使用Stand Advsiple API)PG、MSSQLSPACE、SQLite、DB2、MySQL、GML、PGDUMP、GEJSON、LIKKML、GPKG、WASP、GPX、FILGDB、VFK、BNA、DXF。

现在不推荐使用的coordinatedimmensionapi被替换为调用 * 3D和 * 仔细斟酌的。

一旦M坐标的支持到位,驱动程序将公布支持。

在这个RFC的工作中,支持被内置到内存、shape和pg驱动程序中。对其他司机的支持还有待进一步工作。

公用事业

有一个最低要求和新的可能性。

ogrinfo:报告测量的几何类型,报告测量

ogr2ogr:支持测量的几何类型

ogrlineref:似乎是专门处理措施的,需要更多的思考

gdal_rasterize:测量值可用于老化值

gdal_contour:测量值可用作“高程”值

gdal_grid:measure可以用作“Z”值

文档

所有新的方法/功能都记录在案。

测试套件

至少最初的测试将使用Perl单元测试(swi/Perl/t/measures)完成- * .t)。稍后将扩展自动测试套件。现有的测试不应失败。

兼容性问题

许多支持度量的驱动程序(实际上是数据集和层)需要添加支持。应使用

#define ODsCMeasuredGeometries   "MeasuredGeometries"
#define OLCMeasuredGeometries    "MeasuredGeometries"

创建层的入口点是GDALDataset中的CreateLayer方法。如果数据集不支持测量的几何图形,它将从作为参数获取的几何图形类型中除去测量标志。这符合当前行为非线性几何类型和不支持它们的数据集。

ICreateLayer是所有具有创建层功能的驱动程序实现的,它的参数是几何类型。该方法应使用CPLE_NotSupported调用CPLError(),如果驱动程序不支持度量值,则返回NULL。对于ICreateFeature和ISetFeature也一样。

面向用户的API函数(CreateLayer、CreateFeature和SetFeature)在继续I * 不支持措施的驱动程序中的方法。这种(副作用)可能不是某些使用场景所需要的,但它将遵循非线性几何已经完成的模式。这应该记录在案。

另一种方法是将M个值(或WKT或WKB)存储为属性(标量或向量,具体取决于几何类型)。

需要一个决定。

一定会引入一些不相容性。例如,当当前的XYM as XYZ hack in shape将被适当的XYM替换时。

实施

执行工作将由arijolma完成。

建议的实施将在 https://github.com/ajolma/GDAL-XYZM

投票历史

+1个来自Even,Tamas,Jukka和Daniel