调用esupermap库函数对图层操作的总结

调用Esupermap库函数对图层操作的总结

接到要用esupermap在一个pmf地图文件上画点和线的小任务,但完成这个任务加上周末的话差不多用了一个星期,回想起这一路上碰到的问题及自己怎么一个个把它们干掉的,心中的激动之情油然而生。不过,话说回来,都怪自己对这方面的编程一点都不熟悉,所以特意在此总结一下,以备不时之需:

1. 首先得有一个Pmf地图文件。

话说开始给我的是一个mapinfo导出的地图文件,要用supermap先转换成数据源和工作区间,然后再用esupermap转换成Pmf文件。顺便在此提一下,基本上supermap生成的数据源和工作区间只能由其对应的esupermap版本转换,但恶心的是超图很难弄到esupermap的认证文件,所以转换的时候得花点功夫。可以提供一个小建议,采用截图的方式获取要操作的地图,然后导入supermap(我用的是20xx版),再用esupermap1.0转换,这两个版本虽然不是对应的,但能够转换过来真是庆幸。

Copy师兄的一句话提醒自己:任务是死的,人是活的。真的,不是任务太难完成,是你脑袋不够灵活经验不够多,想不到可以解决的办法。

2. 新建一个evc工程,开始动手了!

首先我觉得是思路的问题,要怎么在一个图层上操作以实现画点,线及其它功能呢?师兄给的建议是:先打开一个地图,然后新建一个图层,再创建点数据集画点,最后创建线数据集画线。

思路清晰了,接下来就是实现了:

第一步: 在EVC 中生成一个WCE MFC AppWizard(Exe)单文档界面工程, 工程名任取, 在stdafx.h 中包含RSFC.h 头文件,该文件中所包含的头文件是对所有eSuperMap 类库的声明和根据编译的环境变量来确定所需的库。也可以根据需要来选择头文件。 如:#include "../SeRSFC/RSFC.h"

第二步:在App 类中加入成员变量CSePMF m_PMF,以便用于管理pmf 文件,对资源,地图数据的操作;类定义之后加入一句“extern CeSuperMapDeskproApp theApp;”这样可以在程序的其他地方调用theApp。

第三步:在视类中加入成员变量CSeMapWnd m_MapWnd,用于对打开的地图进行基本的操作,如放缩、漫游、旋转、刷新、全幅显示、选择对象、添加删除图层、设置图层的显示比例等等,所有一切与用户打交道的都必须涉及到它。

第四步:在视类中添加重载函数OnInitialUpdate(),在函数中添加上初始化代码 m_MapWnd.OnInitialUpdate( &theApp.m_PMF, this ),这样我们的视就跟管理文件的对象theApp.m_PMF 建立了关系。

第五步:在视类的OnDraw 函数中加入以下代码,以便能正确显示地图

CRect rcClient;

GetClientRect( &rcClient );

m_MapWnd.OnDraw( pDC, rcClient, rcClient );

第六步:将资源ID_FILE_OPEN 改为ID_MAP_OPEN,在视类中添加响应该菜单或工具条上相应按钮的函数OnMapOpen(),并添加相应的代码,其函数最后如下: CFileDialog dlgOpenFile ( true, _T("pmf"), NULL, OFN_HIDEREADONLY| OFN_OVERWRITEPROMPT,_T("PMF Files (*.pmf)|*.pmf") );

if( dlgOpenFile.DoModal() == IDOK )

{

if(theApp.m_PMF.IsOpen())

{

m_MapWnd.Close();

theApp.m_PMF.Close();

}

if( theApp.m_PMF.Open(dlgOpenFile.GetPathName()) )

{

CSeMapDef mapdef;

CSeMaps *pMaps = theApp.m_PMF.GetMaps();

CString strMapName = pMaps ->GetMapNameAt(0);

if(pMaps->GetMap(strMapName,mapdef))

{

if(m_MapWnd.OpenMap(mapdef))

{

m_MapWnd.Refresh();

return;

}

}

//如果没有默认地图,就算是图层也要打开一个

CSeDataSource *pDataSource = theApp.m_PMF.GetDefaultDataSource(); m_MapWnd.AddLayer(pDataSource->GetDatasetAt(0));

m_MapWnd.Refresh();

return ;

}

}

3. 在图层上画点和线

第一步:画点。

在菜单栏添加响应函数,点击时弹出对话框,用户输入一个地理坐标(坐标范围可以参照PMF Viewer中显示的地图及手持机屏幕大小来设定)。

将坐标传到一个自定义的CoursePoint结构体中,然后写入文件(其实大可以定义一个CArray的队列来存储,读取时遍历这个队列)。

接下来调用一个函数删除数据集和图层,以保证每次显示时只有一个图层: void CDrawCourseView::ClosePtLayer()

{

CSeDataSource *pDataSource = theApp.m_filePMF.GetDefaultDataSource();

pDataSource->DeleteDataset(_T("CoursePoint"));

m_MapWnd.RemoveLayer(_T("CoursePoint@DataSource"));

m_MapWnd.Refresh();

}

最后是关键了,显示添加的点。我是先读取文件获得添加的点的个数,然后创建点数据集和图层:

void CDrawCourseView::AddPointToLayer()

{

// TODO: Add your command handler code here

CSeDataSource *pDataSource = theApp.m_filePMF.GetDefaultDataSource();//得到默认的数据源

//创建前先删除数据集和图层

BOOL bDeletePointDataset = pDataSource->DeleteDataset(_T("CoursePoint")); BOOL bDeletePointLayer

m_MapWnd.RemoveLayer(_T("CoursePoint@DataSource"));

CSeDataset* pDataset0 = pDataSource->GetDatasetAt(0); //获取第一个数据集 CSeRect2D rcBounds = pDataset0->GetBounds();//得到数据集范围

//创建点数据集

m_pCoursePoints=

pDataSource->CreateDataset(_T("CoursePoint"),CSeDatasetInfo::Point,CSeDataset::HasStyle,rcBounds);

if(m_pCoursePoints!=NULL)

{

CSeLayer* pLayer = m_MapWnd.AddLayer(m_pCoursePoints,true);//添加到地图图层

//设置点的风格

long

nID=theApp.m_filePMF.GetResources()->m_SymbolLib.GetSymbolID(m_CosPtID);

pLayer->m_Style.m_nDimension=0;//设置风格的维数为0,即点

pLayer->m_Style.m_nSymbolStyle=nID;//设置符号类型 pLayer->m_Style.m_nSymbolSize=m_CosPtSize;//设置符号大小 pLayer->m_Style.m_nPenColor=m_CosPtClor;//设置颜色 =

}

}

接着在for循环里添加如下代码:

//地理坐标转换为地图坐标

CPoint point; point.x=(long)floor(Point.x*10000); point.y=(long)floor(Point.y*10000); //设置点的位置 CSeGeoPoint sePoint; sePoint.SetPoint(point.x,point.y); //将点加入记录集 CSeRecordset* pRecd=NULL;//记录集初始化为空 CSeDatasetVector* pCourseLines;//创建一个向量集用于查询

pCourseLines=(CSeDatasetVector*)

(m_MapWnd.GetLayer(_T("CoursePoint@DataSource")))->GetDataset();//查询图层数据集

if (pCourseLines)

pRecd=pCourseLines->QueryWithGeneral(_T(""));//一般查询,返回满足条件的几何对象的记录集

if (pRecd) { if (pRecd->AddNew(&sePoint)>=0) { se_VARIANT variant; variant.vt=VT_I4; variant.lVal=i+1;//点标识加1 CSeVariant varValue=CSeVariant(variant); pRecd->SetFieldValue(_T("SMUSERID"),varValue); pRecd->Update(); } pCourseLines->ReleaseRecordset( pRecd );//释放记录集

}

最后刷新地图,就可以成功显示点了。

第二步:画线。

首先对话框添加点的时候将坐标另存为一个队列

CArray<CSePoint2D ,CSePoint2D >arrPnts;

//转为地图坐标用于连线

CSePoint2D pt;

pt.x = (long)floor(point.x*10000);

pt.y = (long)floor(point.y*10000);

arrPnts.Add(pt);

接着删除线数据集和图层,创建线数据集和线图层,显示各点连成的线。

显示线的代码如下:

for (int i=0;i<arrPnts.GetSize();i++)

{

CSeRecordset* pRecordset=NULL;//记录集初始化为空 CSeDatasetVector* pDV;//创建一个向量集用于查询 pDV=(CSeDatasetVector*) (m_MapWnd.GetLayer(_T("Course@DataSource")))->GetDataset();//查询图层数据集

if (pDV)

pRecordset=pDV->QueryWithGeneral(_T(""));//一般查询,返回满足条件的几何对象的记录集

if (pRecordset) {

//设置航线 CSeGeoLine *pGeoLine = new CSeGeoLine; pGeoLine->Make(arrPnts.GetData(),(arrPnts.GetSize())); pRecordset->AddNew( pGeoLine ); pRecordset->Update(); delete pGeoLine;

pGeoLine = NULL; } pDV->ReleaseRecordset( pRecordset );//释放记录集

}

m_MapWnd.Refresh();//更新地图

第三步:添加地图放大,缩小,平移,显示跟踪点的功能

首先重载鼠标左键Down和Up函数,然后在菜单栏添加各个功能的响应函数。要注意的问题是显示跟踪点时也要用到OnLButtonDown()函数,所以要定义两个宏来避免功能之间的冲突。我是这样实现的:

#define QUERY_MODE_NONE 0

#define QUERY_TRAKING 1

//添加一个整型变量,记下当前的查询模式

long m_nQueryMode;

//设置用户动作状态为放大状态

m_MapWnd.SetAction( CSeDrawParameters::uaZoomIn );

m_nQueryMode = QUERY_MODE_NONE;

//设置用户动作状态为缩小状态

m_MapWnd.SetAction( CSeDrawParameters::uaZoomOut );

m_nQueryMode = QUERY_MODE_NONE;

//设置用户动作状态为平移状态

m_MapWnd.SetAction( CSeDrawParameters::uaPan );

m_nQueryMode = QUERY_MODE_NONE;

m_nQueryMode = QUERY_TRAKING;

m_MapWnd.SetAction( CSeDrawParameters::uaNull );

相关推荐