GDAL矢量驱动拓展

2022-08-30  本文已影响0人  NullUser

GDAL

GDAL文档
GDAL下载
GDAL开发依赖下载
GDAL是一个用于栅格和矢量地理空间数据格式的转换库,采用MIT开源许可,由开源地理空间基金会发布。它为调用程序提供了栅格抽象数据模型和矢量抽象数据模型并包含所有支持的格式。它还提供了一些实用的命令行程序用于数据转换和处理。

OGR

OGR是GDAL项目的一个分支,功能与GDAL类似,只不过它提供对矢量数据的读写支持,包括ESRI Shapefiles,PostGIS等。

矢量数据模型(Vector Data Model)

OGR为矢量数据提供了矢量数据模型。

类概况

体系架构:


体系架构.png

矢量驱动程序实现

通过实现特定格式的驱动,来为OGR加入新的格式支持。这需要实例化GDALDriver类并实现GDALDatasetOGRLayer的子类。GDALDriver实例需要在运行时通过GDALDriverManager进行注册。

1.实现GDALDriver

特定格式的驱动程序类是作为GDALDriver的实例实现的。通常会创建一个GDALDriver实例并通过GDALDeiverManager进行注册。而实例化过程由一个全局C函数进行处理。该函数由自己实现并在内部实例化一个GDALDriver对象。

void registerOGRSPF()
{
    if( GDALGetDriverByName("SPF") != NULL )
        return;

    GDALDriver *poDriver = new GDALDriver();

    poDriver->SetDescription("SPF");
    poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Long name for SPF driver");
    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "spf");
    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drv_spf.html");

    // 为GDALDriver设置函数指针
    poDriver->pfnOpen = OGRSPFDriverOpen;
    poDriver->pfnIdentify = OGRSPFDriverIdentify;
    poDriver->pfnCreate = OGRSPFDriverCreate;

    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");

    GetGDALDriverManager()->RegisterDriver(poDriver);
}

SetDescription("SPF")指定了驱动程序的名称。
SetMetadataItem( const char * pszName, const char * pszValue)设置驱动的元数据信息:

将自定义的实现函数赋值给GDALDriver的函数指针,通过调用GDALDriver的函数指针,以下函数被具体执行:

static GDALDataset* OGRSPFDriverOpen(GDALOpenInfo* poOpenInfo);
static int          OGRSPFDriverIdentify(GDALOpenInfo* poOpenInfo);
static GDALDataset* OGRSPFDriverCreate(const char* pszName, int nXSize, int nYSize,
                                    int nBands, GDALDataType eDT, char** papszOptions);

Open()方法用于打开数据源并返回一个GDALDataset实例,通常被委托给实际的GDALDataset子类,即在内部调用GDALDataset子类实例的Open()方法。

static GDALDataset *OGRSPFDriverOpen( GDALOpenInfo* poOpenInfo )
{
    if( !OGRSPFDriverIdentify(poOpenInfo) )
        return NULL;

    OGRSPFDataSource *poDS = new OGRSPFDataSource();
    if( !poDS->Open(poOpenInfo->pszFilename, poOpenInfo->eAccess == GA_Update) )
    {
        delete poDS;
        return NULL;
    }

    return poDS;
}

Identify()方法可以对数据源进行校验,判断是否是合格数据源。

static int OGRSPFDriverIdentify( GDALOpenInfo* poOpenInfo )
{
    // Does this appear to be an .spf file?
    return EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "spf");
}

create()在用于创建数据,如该驱动用于驱动文件类型的数据时,则可在create()中实现文件的创建。

2.实现GDALDataset子类

GDALDataset子类以一个vector保存多个Layer数据。

class OGRSPFDataSource : public GDALDataset
{
    std::vector<OGRSPFLayer*>   papoLayers;
    int                 nLayers;

public:
  OGRSPFDataSource();
  ~OGRSPFDataSource();

    int                 Open( const char *pszFilename, int bUpdate );

    int                 GetLayerCount() { return nLayers; }
    OGRLayer            *GetLayer( int );

    int                 TestCapability( const char * ) { return FALSE; }
};

Open()方法将会访问数据源信息并创建OGRLayer的子类对象,在实现OGRLayer的子类时,访问数据源信息,并获取要素数据。

int  OGRSPFDataSource::Open( const char *pszFilename, int bUpdate )
{
    if( bUpdate )
    {
        CPLError(CE_Failure, CPLE_OpenFailed,
                "Update access not supported by the SPF driver.");
        return FALSE;
    }

    // Create a corresponding layer.s
    nLayers = 1;

    papoLayers.append(new OGRSPFLayer(pszFilename));

    pszName = CPLStrdup(pszFilename);

    return TRUE;
}

3.实现OGRLayer子类

自定义OGRSPFLayer类继承自OGRLayer。在内部拥有OGRFeatureDefn成员变量,以便访问该图层的元数据信息。

OGRLayer中的纯虚函数有:

class OGRSPFLayer : public OGRLayer
{
    OGRFeatureDefn     *poFeatureDefn;
    FILE               *fp;
    int                 nNextFID;

public:
    OGRSPFLayer( const char *pszFilename );
    ~OGRSPFLayer();

    void                ResetReading();
    OGRFeature *        GetNextFeature();

    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }

    int                 TestCapability( const char * ) { return FALSE; }
};

类内部的OGRFeatureDefn将被多个OGRFeature引用,所有在该类的构造函数和析构函数中也应通过OGRFeatureDefn::Reference()OGRFeatureDefn::Release()对OGRFeatureDefn对象进行引用计数的+1和-1

OGRSPFLayer::OGRSPFLayer( const char *pszFilename )
{
    nNextFID = 0;

    poFeatureDefn = new OGRFeatureDefn(CPLGetBasename(pszFilename));
    SetDescription(poFeatureDefn->GetName());
    poFeatureDefn->Reference();
    poFeatureDefn->SetGeomType(wkbPoint);

    OGRFieldDefn oFieldTemplate("Name", OFTString);

    poFeatureDefn->AddFieldDefn(&oFieldTemplate);

    fp = VSIFOpenL(pszFilename, "r");
    if( fp == NULL )
        return;
}
OGRSPFLayer::~OGRSPFLayer()
{
    poFeatureDefn->Release();
    if( fp != NULL )
        VSIFCloseL(fp);
}

重写GetNextFeature(),在函数体内访问数据源获取到每一个feature的信息,并创建OGRFeature对象后返回。

OGRFeature *OGRSPFLayer::GetNextFeature()
{
  /* 从数据源获取到下一个feature的数据 */
  ......
  {
    OGRFeature *poFeature = new OGRFeature(poFeatureDefn);

    poFeature->SetGeometryDirectly(new OGRPoint(dfX, dfY));
    poFeature->SetField(0, pszName);
    poFeature->SetFID(nNextFID++);
    if(/*match*/)
    {
      return poFeature;
    }
    else
    {
      delete poFeature;
    }
  }

}

OGRLayer基类拥有成员变量:OGRLayer::m_poFilterGeomOGRLayer::m_poAttrQuery分别对几何和属性进行过滤,以便筛选出符合要求的feature,可以在GetNextFeature()方法中进行判断:

        if( (m_poFilterGeom == NULL ||
            FilterGeometry(poFeature->GetGeometryRef())) &&
            (m_poAttrQuery == NULL ||
            m_poAttrQuery->Evaluate(poFeature)) )
            return poFeature;

        delete poFeature;

重写OGRLayer::ResetReading(),在函数体内重置feature的索引,代表重新获取feature,与OGRLayer::GetNextFeature()联动。

void OGRSPFLayer::ResetReading()
{
    VSIFSeekL(fp, 0, SEEK_SET);
    nNextFID = 0;
}

4.GDALDataset虚函数

重点实现:

 <ul>
  <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
  <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
          layers.<p>
  <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
          datasource support CreateGeomField() just after layer creation.<p>
  <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
          geometries.<p>
  <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
          transactions.<p>
  <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
          transactions through emulation.<p>
  <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
          GetNextFeature() implementation, potentially returning features from
          layers in a non sequential way.<p>
  <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
         CreateFeature() on layers in a non sequential way.<p>
 </ul>o

非重点实现:

5.OGRLayer虚函数

重点实现:

非重点实现:

上一篇 下一篇

猜你喜欢

热点阅读