目录
1. 背景简介
SuperMap iObjects C++
是 SuperMap GIS 系列软件的基础内核,他使用标准 C++ 开发,集成了 SuperMap 高性能、跨平台技术。以 C++ API 的方式向用户提供基础 GIS 功能。
虽说 iObjects C++ 组件性能高,但 iObjects C++ 组件中提供的开发示例 DEMO 相比 iObjects .NET / Java 组件较少,基于 iObjects C++ 组件开发门槛较高且帮助文档关于 iObjects C++ API 接口说明较少,使之客户基于 iObjects C++ 组件开发难度较高,因此提供该教程和对应示例 DEMO 以供参考。
该教程基于 SuperMap iObjects C++
11i 组件实现 工作空间、数据源、数据集 管理功能,包括:工作空间新建、打开、保存、另存、关闭;数据源新建、打开、保存、关闭;点、线、面、三维点、三维线、三维面、CAD、模型、栅格、影像、属性表等数据集新建、关闭等功能。
这些功能均属于 iObjects C++
核心组件模块,因此仅需核心组件许可权限即可正常使用。iObjects C++
组件许可模块详情如下:
2. 开发环境配置
2.1. 开发环境依赖
软件产品 | 版本 | 下载地址 | 备注 |
---|---|---|---|
SuperMap iObjects C++ | 11i | SuperMap iObjects C++ 11i 下载地址 | 推荐使用 SuperMap iObjects C++ 11i 版本组件 |
Visual Studio | 2022 | Visual Studio 2022 社区版下载地址 | 在安装 Visual Studio 2022 时,需按照 C++ 库 |
2.2. 搭建 MFC 项目
-
从 Visual Studio 2022 社区版创建 MFC 应用
-
创建 基于对话框 的 MFC,选择 应用程序类型 后,直接点击 完成
上述 2 步执行结束后,已成功创建最简单的 MFC 应用程序,接下来需要进一步对已创建的 MFC 应用程序配置
SuperMap iObjects C++ 11i
组件开发环境依赖。
2.3. 配置 iObjects C++ 11i 组件开发环境依赖
-
配置 C/C++ 环境
-
将 iObjects C++ 目录\include 和 iObjects C++ 目录\include\private 目录添加到 C/C++》附加包含目录 项
-
将 _UGUNICODE 配置到 C/C++》预处理器定义 项
-
在 C/C++》语言 项配置 WChar_t 视为内置类型
-
将 /bigobj 添加到 C/C++》命令行 项
-
-
配置 链接器 环境
-
将 iObjects C++ 目录\lib\lib_x64 添加到 链接器》附加库目录 项
-
将下述库文件添加到 链接器》附加依赖项 项
SuAllocation.lib SuAnalyst3D.lib SuAnimation.lib SuBase.lib SuBase3D.lib SuBGDataCompiler.lib SuBPlusTree.lib SuCacheBuilder.lib SuCacheBuilder3D.lib SuCacheFile.lib SuChartBase.lib SuChartToolkit.lib SuCompactFile.lib SuCVToolkit.lib SuDataCheck.lib SuDataExchange.lib SuDB2CI.lib SuDCPackager.lib SuDCToolkits.lib SuDrawing.lib SuDrawing3D.lib SuDrawingLayout.lib SuElement.lib SuEngine.lib SuEngineBaiduMaps.lib SuEngineBingMaps.lib SuEngineDB2.lib SuEngineES.lib SuEngineExtendFile.lib SuEngineGanos.lib SuEngineGaoDeMaps.lib SuEngineGBase.lib SuEngineGoogleMaps.lib SuEngineImagePlugin.lib SuEngineMapWorldMaps.lib SuEngineMySQL.lib SuEngineODBC.lib SuEngineOGC.lib SuEngineOGDC.lib SuEngineOpenStreetMaps.lib SuEngineOracle.lib SuEnginePG.lib SuEnginePGis.lib SuEngineRest.lib SuEngineSCV.lib SuEngineSMCloud.lib SuEngineSpatialite.lib SuEngineSQLPLUS.lib SuEngineSsp.lib SuEngineUDB.lib SuEngineXYZTile.lib SuFileParser.lib SuFileParser3DModel.lib SuFileParser3ds.lib SuFileParserAcad.lib SuFileParserBitMap.lib SuFileParserCSV.lib SuFileParserDEM.lib SuFileParserE00.lib SuFileParserENC.lib SuFileParserFME.lib SuFileParserGDAL.lib SuFileParserKML.lib SuFileParserLidar.lib SuFileParserMAPGIS.lib SuFileParserMitab.lib SuFileParserNetCDF.lib SuFileParserOGR.lib SuFileParserPointCloud.lib SuFileParserRAW.lib SuFileParserS3MB.lib SuFileParserSCV.lib SuFileParserSGM.lib SuFileParserTEMS.lib SuFMELicense.lib SuGeneralization.lib SuGeoCode.lib SuGeometricNetwork.lib SuGeometry.lib SuGeometry3D.lib SuGeometryCAD.lib SuGeometryConverter.lib SuGeometryLayout.lib SuGeometryPlot.lib SuGeoOperation.lib SuGeoOperation3D.lib SuGraphics.lib SuGraphics3D.lib SuGraphics3DGameEngine.lib SuGraphics3DOGRE.lib SuGraphicsPDF.lib SuGraphicsPS.lib SuGraphicsW.lib SuGridAnalyst.lib SuGridAnalystOpenCL.lib SuGridModeling.lib SuLayer3DDataset.lib SuLayer3DDatasetModel.lib SuLayer3DFile.lib SuLayer3DMap.lib SuLayer3DTree.lib SuLayoutEditor.lib SuLinearReference.lib SuLogistics.lib SuMap.lib SuMapEditor.lib SuMapMatching.lib SuMapServiceStub.lib SuMGAnimationExp.lib SuMGAuxiliaryPlotting.lib SuMGCommon.lib SuMGMapData.lib SuMGMovingTarget.lib SuMGObjects.lib SuMGSituation.lib SuMGSituationMonitor.lib SuMGSituationSimulation.lib SuMongoCI.lib SuMosaic.lib SuMosaicOpenCV.lib SuMySQLCI.lib SuNetToolkit.lib SuNetworkBuilder.lib SuNetworkEnvironment.lib SuNTopoDataCompiler.lib SuNTopoIndexTree.lib SuODBCCI.lib SuOGCParser.lib SuOGDC.lib SuOracleCI.lib SuOverlay.lib SuParticleSystem.lib SuPathAnalyst.lib SuPathAnalystCH.lib SuPathNavi.lib SuPluginCommon.lib SuPluginGECache.lib SuPluginGlobalCache.lib SuPluginGridCache.lib SuPluginMapCache.lib SuPluginMapCache50.lib SuPluginWebCache.lib SuPostgreSQLCI.lib SuProjection.lib SuProjectionProj.lib SuProjectionWKT.lib SuProximity.lib SuPublicTransport.lib SuRasterData.lib SuRectify.lib SuRender.lib SuRepresentation.lib SuRStarTree.lib SuScene.lib SuSceneEditor.lib SuSpatialIndex.lib SuSpatialQuery.lib SuSQLiteCI.lib SuStream.lib SuSymbol.lib SuSymbolAlgo1.lib SuSymbolAlgo2.lib SuSymbolAlgo3.lib SuSymbolAlgo4.lib SuSymbolAlgo5.lib SuSymbolAlgo6.lib SuSymbolAlgo7.lib SuSymbolExchange.lib SuSymbolMarker3D.lib SuTheme3DBase.lib SuTileStorage.lib SuToolkit.lib SuToolkit3D.lib SuToolkitPointCloud.lib SuToolkitVDB.lib SuTopoBase.lib SuTopoBuilder.lib SuVRDevices.lib SuWorkspace.lib SuWrapc.lib SuAlgorithm.lib SuAlgorithm3D.lib
-
此处是为了方便,便直接将
SuperMap iObjects C++
的全部 依赖项 都直接添加到 MFC 应用程序依赖项。若觉得SuperMap iObjects C++
的全部 依赖项 太多,则可以适当添加需要的使用的部分 依赖项。
3. 功能实现
接下来是关于工作空间、数据源、数据集管理的核心功能调用接口以及实现逻辑,具体代码实现可直接参考下述实现代码。
3.1. 打开工作空间
打开工作空间的操作主要包括 2 步:1. 构建工作空间连接信息(工作空间路径、版本、类型和名称);2. 根据构建的工作空间连接信息打开指向的工作空间。详细编码可参考以下实现:
// 构建工作空间连接信息
UGWorkspaceConnection workspaceConnection = UGWorkspaceConnection();
workspaceConnection.m_strServer = workspaceFilePath;
workspaceConnection.m_nVersion = UG_WORKSPACE_VERSION_20120328;
workspaceConnection.m_nWorkspaceType = GetWorkspaceType(workspaceFileExt);
workspaceConnection.m_bFailIfExists = false;
workspaceConnection.m_strWorkspaceName = workspaceFileName;
// 打开工作空间
m_workspace = new UGWorkspace();
if (m_workspace->Open(workspaceConnection))
{
m_workspace->SetName(workspaceConnection.m_strWorkspaceName);
m_workspace->SetCaption(workspaceConnection.m_strWorkspaceName);
}
3.2. 另存工作空间
另存工作空间的操作流程与打开工作空间一样,详细编码可参考以下实现:
// 构建工作空间连接信息
UGWorkspaceConnection workspaceConnection = UGWorkspaceConnection();
workspaceConnection.m_strServer = workspaceFilePath;
workspaceConnection.m_nVersion = UG_WORKSPACE_VERSION_20120328;
workspaceConnection.m_nWorkspaceType = GetWorkspaceType(workspaceFileExt);
workspaceConnection.m_bFailIfExists = false;
workspaceConnection.m_strWorkspaceName = workspaceFileName;
m_workspace->SetName(workspaceConnection.m_strWorkspaceName);
m_workspace->SetCaption(workspaceConnection.m_strWorkspaceName);
// 另存工作空间
if (m_workspace->SaveAs(workspaceConnection)) {}
3.3. 新建文件型数据源
新建文件型数据源需要指定文件路径、文件别名以及数据源类型,其中 UGEngineType::Spatialite 对应 UDBX 文件型数据源,UGEngineType::UDB 对应 UDB 文件型数据源,建议根据实际需求设置适合的数据源类型。
注意: 在获取数据源连接信息的时候,需要获取其引用,否则无法正确的修改数据源对象内部的连接信息,则会导致新建数据源的时候执行失败。
// 构建数据源信息
UGDataSource* datasource = UGDataSourceManager::CreateDataSource(UGEngineType::Spatialite);
UGDsConnection& dsConn = datasource->GetConnectionInfo();
dsConn.m_strServer = filePath;
dsConn.m_strAlias = fileTitle;
dsConn.m_nType = UGEngineType::Spatialite;
// 新建数据源
if (!datasource->Create())
{
datasource->Close();
delete datasource;
}
else
{
// 数据源新建成功,添加到当前工作空间中
if (!m_workspace->m_DataSources.Insert(dsConn.m_strAlias, datasource) || !m_workspace->Save()) {}
}
3.4. 打开文件型数据源
打开文件型数据源的操作流程与新建文件型数据源一样,详细编码可参考以下实现:
// 构建数据源信息
UGDataSource* datasource = UGDataSourceManager::CreateDataSource(UGEngineType::Spatialite);
UGDsConnection& dsConn = datasource->GetConnectionInfo();
dsConn.m_strServer = filePath;
dsConn.m_strAlias = fileTitle;
dsConn.m_nType = UGEngineType::Spatialite;
// 打开数据源
if (!datasource->Open())
{
datasource->Close();
delete datasource;
}
else
{
// 数据源打开成功,添加到当前工作空间中
if (!m_workspace->m_DataSources.Insert(dsConn.m_strAlias, datasource) || !m_workspace->Save()) {}
}
3.5. 新建矢量数据集
新建矢量数据集的操作流程都是一样的,唯有数据集类型不同,因此简单封装了以下接口用于复用新建不同类型的矢量数据集,包括:二维点(UGC::UGDataset::Point)、二维线(UGC::UGDataset::Line)、二维面(UGC::UGDataset::Region)、三维点(UGC::UGDataset::PointZ)、三维线(UGC::UGDataset::LineZ)、三维面(UGC::UGDataset::RegionZ)、模型(UGC::UGDataset::Model)、CAD(UGC::UGDataset::CAD)、属性表(UGC::UGDataset::Tabular)等。
/// <summary>
/// 创建矢量数据集
/// </summary>
/// <param name="workspace">工作空间</param>
/// <param name="datasetType">数据集类型</param>
/// <param name="datasetName">数据集名称</param>
/// <returns>是否创建成功</returns>
UGbool CWDDManagerDlg::CreateDefaultDatasetVector(UGWorkspace* workspace, UGDataset::DatasetType datasetType, std::string datasetName)
{
UGbool isCreated = FALSE;
int datasourcesCount = workspace->m_DataSources.GetCount();
if (datasourcesCount > 0)
{
UGString datasourceAlias;
UGDataSource* datasource;
if (workspace->m_DataSources.GetAt(0, datasourceAlias, datasource) && datasource != nullptr)
{
// 获取可用的数据集名称
UGString strName;
strName = GetAvailableDatasetName(datasource, strName.FromStd(datasetName));
// 构建矢量数据集信息
UGDatasetVectorInfo datasetVectorInfo;
datasetVectorInfo.m_strName = strName;
datasetVectorInfo.m_strTableName = strName;
datasetVectorInfo.m_nCodecType = UGDataCodec::CodecType::envNONE;
datasetVectorInfo.m_nSmIDType = UGDataset::SmIDType::INT64;
datasetVectorInfo.m_nType = datasetType;
// 根据矢量数据集信息新建矢量数据集
UGDatasetVectorPtr datasetVector = datasource->CreateDatasetVector(datasetVectorInfo);
if (datasetVector == nullptr)
{
return isCreated;
}
else
{
isCreated = TRUE;
}
}
}
return isCreated;
}
3.6. 新建栅格数据集
新建栅格数据集与新建矢量数据集类似,封装以下接口可用于构建简单的单波段栅格(UGC::UGDataset::Grid)、影像(UGC::UGDataset::Image)数据集。
/// <summary>
/// 创建栅格数据集
/// </summary>
/// <param name="workspace">工作空间</param>
/// <param name="datasetType">数据集类型</param>
/// <param name="datasetName">数据集名称</param>
/// <returns>是否创建成功</returns>
UGbool CWDDManagerDlg::CreateDefaultDatasetRaster(UGWorkspace* workspace, UGDataset::DatasetType datasetType, std::string datasetName)
{
UGbool isCreated = FALSE;
int datasourcesCount = workspace->m_DataSources.GetCount();
if (datasourcesCount > 0)
{
UGString datasourceAlias;
UGDataSource* datasource;
if (workspace->m_DataSources.GetAt(0, datasourceAlias, datasource) && datasource != nullptr)
{
// 获取可用的数据集名称
UGString strName;
strName = GetAvailableDatasetName(datasource, strName.FromStd(datasetName));
// 构建栅格数据集信息
UGDatasetRasterInfo datasetRasterInfo;
datasetRasterInfo.m_strName = strName;
datasetRasterInfo.m_strTableName = strName;
datasetRasterInfo.m_rc2Bounds = UGRect2D(-200.0, -200.0, 200.0, 200.0);
datasetRasterInfo.m_eBlockSize = UGDatasetRasterInfo::IBSizeOption::IBS_64;
datasetRasterInfo.m_nHeight = 800;
datasetRasterInfo.m_nWidth = 800;
datasetRasterInfo.m_nType = datasetType;
datasetRasterInfo.SetPixelFormat(OGDC::PixelFormat::IPF_DOUBLE);
datasetRasterInfo.SetNoValue(-9999.0);
// 构建栅格波段信息
UGBandInfo bandInfo;
bandInfo.m_bAvail = TRUE;
bandInfo.m_dMaxZ = 10000.0;
bandInfo.m_dMinZ = -1000.0;
bandInfo.m_nBandID = 1;
bandInfo.m_nIndex = 1;
bandInfo.m_nCodecType = UGDataCodec::CodecType::enrNONE;
bandInfo.SetPixelFormat(OGDC::PixelFormat::IPF_DOUBLE);
bandInfo.SetNoValue(-9999.0);
datasetRasterInfo.Add(bandInfo);
// 根据栅格数据集信息新建栅格数据集
UGDatasetRasterPtr datasetRaster = datasource->CreateDatasetRaster(datasetRasterInfo);
if (datasetRaster == nullptr)
{
return isCreated;
}
else
{
isCreated = TRUE;
}
}
}
return isCreated;
}
3.7. 关闭数据集
关闭数据集的时候需要执行 2 步操作:1. 关闭数据集本身;2. 从需要被关闭的数据集所在数据源中移除该数据集。此 2 步骤执行结束后,即完整的关闭数据集。
注意: 建议在关闭数据集后调用数据源紧缩接口(Compact),否则当前数据源在磁盘上占用的文件大小不会刷新,依然会保留关闭数据集之前的文件大小。
/// <summary>
/// 关闭数据集
/// </summary>
/// <param name="workspace">工作空间</param>
/// <param name="datasetType">数据集类型</param>
/// <returns>是否关闭成功</returns>
UGbool CWDDManagerDlg::CloseDataset(UGWorkspace* workspace, UGDataset::DatasetType datasetType)
{
if (IsExistedDataset(workspace, datasetType))
{
UGbool isDeleted = FALSE;
UGint datasourcesCount = workspace->m_DataSources.GetCount();
for (size_t i = 0; i < datasourcesCount; i++)
{
UGString datasourceAlias;
UGDataSource* datasource;
if (workspace->m_DataSources.GetAt(0, datasourceAlias, datasource) && datasource != nullptr)
{
UGint datasetCount = datasource->GetDatasetCount();
OgdcUnicodeStringArray datasetNames = datasource->GetDatasetNames();
for (size_t j = 0; j < datasetNames.GetSize(); j++)
{
UGDatasetPtr dataset = datasource->GetDataset(datasetNames.GetAt(j));
if (dataset->GetType() == datasetType)
{
// 关闭数据集
dataset->Close();
// 从数据源中删除数据集
if (!datasource->DeleteDataset(dataset->GetName()) || !datasource->SaveInfo() || !datasource->Compact(TRUE))
{
return isDeleted;
}
else
{
isDeleted = TRUE;
break;
}
}
}
}
if (isDeleted)
{
break;
}
}
return isDeleted;
}
}
4. 总结
通过上述核心功能逻辑,即可非常轻松的基于 SuperMap iObjects C++ 11i
组件实现对工作空间、数据源、数据集的管理,以下是 Demo 演示:
若仔细阅读上述流程以及实现逻辑后仍然感觉无从入手,不清楚究竟该如何基于这些核心逻辑实现代码应该如何在 MFC 窗口程序中组合使用,不用着急也不用担心,对于 C++ MFC 开发新手,特意提供了基于上述核心逻辑实现的 MFC 示例工程 《基于 iObjects C++ 11i 组件对工作空间、数据源、数据集管理》,可直接下载该开源示例,根据本篇博客对示例工程配置开发环境后即可轻松运行。