摘 要 本文分析了传统的从mapgist文件到Shapefile文件转换的方法,并加以改进解决了大量MapGis文件和Shapefile文件快速转换的问题。经过用户实践证明,该方法简单有效。关键词 MapGis文件;Shapefile;快速转换 Research of Rapid Converting MapGis file to Shapefile
Chen Xiaohu Dong Zhu Chen Kai(Chengdu Institute of Survey and Investigation,Chengdu 610081,China)
Abstract This analyses the traditional method of translating MapGis file into ShapeFile and improves the method to solve the problem of a lot of Mapgis files rapid translating Shapefile.It has been confirmed that the means is efficient,through the author’s practice.
Key words MapGis file;Shapefile;rapid translating
1 引言
实际生产过程中常常利用MapGis完成数据生产及加工,然后转换到Shapefile文件格式,利用ArcGIS来建立数据库,并进行GIS分析与应用。这就涉及了MapGis文件转换Shapefile文件的问题。MapGis早期版本就具有了将Shapefile文件批量转换为mapgis文件的功能,并且Mapgis 65以后已经具有了将单个文件转换为shapefile文件的功能。但是Mapgis转换为Shapefile文件的几个问题一直没有得到很好解决。影响了Mapgis与Arcgis的数据共享。
(1)MapGis没有批量将文件转换为Shapefile文件的功能。当有大量MapGis文件需要转换到Shapefile文件时,人工一个文件一个文件进行转换不仅效率低,而且很容易出错。
(2)MapGis文件本身带有颜色和符号信息,可是转换为Shapefile文件时,这些信息将全部丢失。在ArcGis里没有任何MapGis的原始符号信息(如子图号,颜色),要重新赋颜色符号将是非常困难的事情。
(3) Mapgis文件里文字作为注释类型存在,而在Shapefile文件没有注释类型,只有点(point)文件,通过对字符类型字段的标注来实现文本的显示。
2 传统的处理方法
在Mapgis65以前,通常是将mapgis文件转换为第三方文件格式,然后再转换为Shapefile文件时;MapGis65以后,可以单个文件单个文件转换为Shapefile文件,但是转换后失去了所有的符号信息。
为了方便在ArcGIS里重新给Shapefile文件赋上颜色符号,通常手工增加一些字段如“图层”、“颜色”、“子图号”……;然后使用MapGis编缉模块的“根据参数赋属性”将参数赋到属性字段里。然后将文件转换为Shapefile文件。
传统方法转换MapGis点文件,首先将点文件分离为子图文件和注释文件,然后分别增加参数属性字段,注释文件还要增加一个文本字段,使用“注释赋为属性”,将文本内容保存到属性字段里。最后将文件转换为Shapefile文件。
传统的转换方法烦琐复杂而且容易出错,幸好,MapGis提供了提供完整的二次开发函数库。用户完全可以在MapGIS平台上开发面向各自领域的应用系统。本文介绍了利用Visual C++6.0与MapGis二次开发函数库实现MapGis文件快速转换Shapefile文件的研究。
3 程序设计与实现
程序分成两个模块,第一个是“图元参数赋属性”模块;第二个是“批量转换Shapefile”模块。考虑到图元参数赋给属性后,用户可以将带有新属性的MapGis文件转换为其它格式,没有将它们合在一起,分开实现功能以增加灵活性。下文详细介绍两个模块的实现。
3.1 图元参数赋属性模块
MapGis类型文件拥有不同的后缀:点文件(.wt);线文件(.wl);面文件(.wp)。不同类型的文件需要添加不同的图元参数属性字段;如子图文件需增加“子图号”,“子图高”……;线文件则增加“线型”,“线宽”……。该模块首先根据文件后缀判断是否是Mapgis文件,同时判断出文件类型,再根据不同的文件类别加不同的参数属性字段,并将图元参数作为属性赋给参数属性字段。现以点文件为例说明该模块的实现。
3.1.1 将点文件分离为子图与注释
Shapefile文件通过标注属性字段来实现文件显示,所以MapGis的点文件必须将子图与注释分离成不同的文件,分别转换为Shapefile文件。
(1) 子图参数赋属性
打开MapGis点文件并装入点工作区, 新建“子图号”、“子图高”、“子图角度”、“颜色”、“图层”共五个字段,依次遍历文件中的每个图元并判断图元类型,如果是子图则获取子图参数并将参数值赋给对应的属性字段;如果是注释则删除。当遍历结束后另存一个新的点文件即得到一个有图元参数的子图文件。主要代码如下:
PNT_INFO pntInfo;
CFIELD_HEAD t[5]; char *att;
//获取点文件的属性结构
_GetAttStru(ai,PNT,&stru);
//定义新增加的字段集
lstrcpy(t[0].fieldname,"子图号");t[0].fieldtype=STR_TYPE;t[0].msk_leng=20;
lstrcpy(t[1].fieldname,"子图高");t[1].fieldtype=STR_TYPE;t[1].msk_leng=20;
lstrcpy(t[2].fieldname,"子图角度");t[2].fieldtype=STR_TYPE;t[2].msk_leng=20;
lstrcpy(t[3].fieldname,"颜色");t[3].fieldtype=STR_TYPE;t[3].msk_leng=20;
lstrcpy(t[4].fieldname,"图层");t[4].fieldtype=STR_TYPE;t[4].msk_leng=20;
//将新定义的字段集插入点文件的属性结构
c=_InsertStruFld(ai,PNT,5,t,1);
//获取点文件图元个数
if(_GetPntNum(ai,&i,&n)==0)
return 0;
//遍历所有图元
for(i=1;i<n;i++)
{
if(_GetPntInfo(ai,i,&pntInfo)<=0) //获取第i个图元的图形信息
continue; //若获取失败眺出本次循环
if(_GetAtt(ai,PNT,i,&stru,&att)<=0) //获取第i个图元的属性信息
continue;
if (pntInfo.type==PNT_NOTE) //如果点类型是注释
{
_DelPnt( ai,i); //删除点图元
continue;
}
//若图元类型是子图,则获取图元参数并存入属性
if (pntInfo.type==PNT_SUB)
{
sTem.Format("%ld",pntInfo.info.sub.subno);_SetFldFromStr(att,stru,"子图号",LPSTR(LPCTSTR(sTem)));
sTem.Format("%f",pntInfo.info.sub.height);_SetFldFromStr(att,stru,"子图高",LPSTR(LPCTSTR(sTem)));
sTem.Format("%f",pntInfo.info.sub.angle);_SetFldFromStr(att,stru,"子图角度",LPSTR(LPCTSTR(sTem)));
sTem.Format("%hd",pntInfo.iclr);_SetFldFromStr(att,stru,"颜色",LPSTR(LPCTSTR(sTem)));
sTem.Format("%hd",pntInfo.layer);_SetFldFromStr(att,stru,"图层",LPSTR(LPCTSTR(sTem)));
_WritePntAtt(ai,i,stru,att); //写入点图元属性
} (2) 注释参数赋属性
再次打开同一个点文件并装入点工作区, 新建“内容”、“字符高”、“字符宽”、“字符间距”、“字符角度”、“中文字体”、“颜色”、“图层”共五个字段,依次遍历文件中的每个图元并判断图元类型,如果是注释则获取注释参数并将参数值赋给对应的属性字段,并将注释的文本内容赋给“内容”字段;如果是子图则删除该图元。当遍历结束后另存一个新的点文件得到一个有图元参数和文本内容的注释文件。
3.1.2 线文件与面文件的处理
线文件需增加“线型”、“颜色”、“线宽”、“X系数”、“Y系数”、“图层”六个字段。面文件需增加“填充颜色”、“填充图案”、“图案高度”、“图案宽度”、“图案颜色”、“图层”六个字段。MapGis的线文件与面文件处理相对点文件处理要简单一些,只需打开文件遍历所有图元一次并将获取的图元参数值赋给对应的属性字段即可。
3.2 批量转换Shapefile模块
MapGis文件与Shapefile内部文件结构完全不同,并且存在一些特殊的文件结构。比如在Shapefile文件中,对象ID属性具有唯一性,在MapGis文件里,图元ID属性却是可以重复的,另外MapGis文件里,图元被删除后,仅仅是逻辑上的删除,只有压缩存盘后,被删除的图元才真正的被物理删除。 为了避免转换出错,在转换前需要对MapGis文件进行一些特殊的处理。
3.2.1 遍历指定文件夹内MapGis文件
打开指定文件夹,开始遍历文件夹里所有的MapGis文件:点文件(.wt)、线文件(.wl)、面文件(.wp):
//进行循环读取,对每个文件进行转换
HANDLE hFind;
WIN32_FIND_DATA dataFile;
BOOL bMoreFiles=TRUE;
hFind=FindFirstFile(strDir,&dataFile);
while(hFind!=INVALID_HANDLE_VALUE && bMoreFiles==TRUE)
{
if(dataFile.dwFileAttributes==FILE_ATTRIBUTE_ARCHIVE)
{
…………
bMoreFiles=FindNextFile(hFind,&dataFile);
}
}
3.2.2 对打开的文件进行压缩存盘
MapGis文件进行删除图元操作后,图元仅仅是被逻辑删除,在缺省情况下,保存工作区内容时,不清除被删掉的图元。重新装入文件时,被删掉的图元依然存在。只有将工作区的压缩标志设置为1,在保存工作区内容时,才能将被删除的图元将从物理上被清除掉。
strFile0=m_strSourceFolder+"\\"+strFile;
//打开指定的数据文件对应的工作区,并将数据装入到新工作区中
Pai=_OpenFileArea(ahinst,strFile0.GetBuffer(strFile0.GetLength())); strFile=strFile.Left(strFile.GetLength()-3);
strFile=m_strFolder+"\\"+strFile;
//将工作区压缩标志设为1
_SetPackFlag(Pai,1);
//保存工作区内容
_SaveAFile(Pai,strFile0.GetBuffer(strFile0.GetLength()));
3.2.3 对文件进行重置缺省ID处理
重置缺省ID实质上就是把图元唯一的图元号赋给它的ID属性。
MapGis文件的图元ID属性不是唯一的,可以重复,Shapefile的对象ID属性(ObjectID)却是唯一的。在转换前对文件进行重置缺省ID操作有助于提高文件转换的成功率。以下是点文件(.wt)的重置缺省ID源代码
//取图元个数
if(_GetPntNum(Pai,&i,&n)==0)
return ;
//循环取所有记录
for(i=1;i<n;i++)
{
//取第i条记录
if(_GetAtt(Pai,PNT,i,&stru,&att)<=0)
continue;
//根据字段名称设置字段值
_SetFld(att,stru,"ID",(char *)&i);
//写点定类型图元属性
_WritePntAtt(Pai,i,stru,att);
}
3.2.4 将文件转换为Shape文件
MapGis文件用后缀名来区分点(.wt)、线(.wl)、面(.wp)文件,而Shapefile文件后缀没有点、线、面的区别。批量转换时,为避免转换后出现同名文件相互覆盖的情况,我们转换后的点文件名加”p”,线文件名加”l”,面文件名加”r”来以示区别。调用转换shape函数
//将点文件转换为shape文件
_ShapeOut(Pai,LPTSTR(LPCTSTR(strFile)));
4 结论
该程序在生产实践中的应用表明它能最大限度的减少MapGis文件转换到Shapefile文件过程中出错的可能性,极大的提高了生产效率,程序实现的方法简单,有效而且可靠。
|