S57文件结构分析.docx
- 文档编号:11173880
- 上传时间:2023-02-25
- 格式:DOCX
- 页数:13
- 大小:293.53KB
S57文件结构分析.docx
《S57文件结构分析.docx》由会员分享,可在线阅读,更多相关《S57文件结构分析.docx(13页珍藏版)》请在冰豆网上搜索。
S57文件结构分析
S57文件存储构造
一、DDR构造
DDR中定义了文件的总体信息,包括文件名,字段名,字段类型,字段格式和长度,字段间的关系,及子字段.
1.文件头区
24个字节,容如下表
记录长度是指DDR的总长度.
2.记录区
记录区从第25个字节开场,直到字节值=30为止.30称为字段终结符〔FT=30〕.
每个记录的长度由:
文件头区中的,字段长度大小,字段位置大小,字段标识的大小之和决定.
每个记录描述一个字段的根本信息〔名称、长度、起始位置〕.
每个记录是定长的.
3.字段区
记录区中的每一条记录对应一个字段,然后在字段描述区进一步给出字段的具体信息。
每个字段的描述信息之间由字段终结符〔FT30〕隔开。
每个字段的描述信息部不同局部由单元终结符〔UT=31〕隔开。
其中每个字段描述信息的第一局部为字段的控制信息,共9个字节组成。
DDR的第一个字段为控制字段,字段名为"0000"〔地址为:
目录区后的第一个字节〔文件头+目录区的长度〕〕
控制字段给出了文件名、及全部字段的构造信息。
例如:
如下控制字段数据可生成对应的字段构造图
DDR的其余字段为数据描述字段,〔地址为:
目录区后的第一个字节+该字段的偏移量〕。
例如:
如下的字段描述字段为
4.程序实现
S57-文件对应的DDFModule类,在该类中读入DDR信息。
其中,DDR文件头存入achLeader中。
charachLeader[nLeaderSize];//nLeaderSize=24
DDR中完整数据存入:
pachRecord中。
pachRecord=(char*)CPLMalloc(_recLength);//_recLength在文件头中的第一个域中定义。
根据DDR文件头中定义容和终止符计算DDR中字段的记录个数。
for(i=nLeaderSize;i<_recLength;i+=nFieldEntryWidth)
{
if(pachRecord[i]==DDF_FIELD_TERMINATOR)
break;
nFDCount++;
}
在字段的每一条记录中,得到每一个字段的标识、长度、起始位置〔从记录区后面的第一个字节开场计算〕。
根据记录区中定义的各字段标识、长度、起始位置在字段区中取到该字段对应的描述信息。
主要包括字段名称、描述及在后面数据区中占的位置和转换格式。
例如SG2D对应的描述为:
定义了Y、X坐标为2个实数。
程序处理中,将每一个记录定义为一个对象,其基类为:
DDFFieldDefn
DDFFieldDefn*poFDefn;
AddField(poFDefn);
voidDDFModule:
:
AddField(DDFFieldDefn*poNewFDefn)
{
nFieldDefnCount++;
papoFieldDefns=(DDFFieldDefn**)
CPLRealloc(papoFieldDefns,sizeof(void*)*nFieldDefnCount);
papoFieldDefns[nFieldDefnCount-1]=poNewFDefn;
}
其中:
DDFFieldDefn**papoFieldDefns;
注:
*poFDefn本身为DDFFieldDefn指针,而每一个字段对应一个指针,故papoFieldDefns为二级指针。
特别注意:
switch(pachFieldArea[0])
//字段区的第一个字节,即控制字段的第一个字节
{
case'0':
_data_struct_code=dsc_elementary;
break;
}
if(_data_struct_code!
=dsc_elementary)
{
if(!
BuildSubfields())
returnFALSE;
if(!
ApplyFormats())
returnFALSE;
}
其中,BuildSubfields定义如下:
intDDFFieldDefn:
:
BuildSubfields()
{
char**papszSubfieldNames;
constchar*pszSublist=_arrayDescr;
//字段描述区字符,在Initialize中定义
if(pszSublist[0]=='*')
{
bRepeatingSubfields=TRUE;
pszSublist++;
}
papszSubfieldNames=CSLTokenizeStringplex(pszSublist,"!
",
FALSE,FALSE);
intnSFCount=CSLCount(papszSubfieldNames);
for(intiSF=0;iSF { DDFSubfieldDefn*poSFDefn=newDDFSubfieldDefn; poSFDefn->SetName(papszSubfieldNames[iSF]); AddSubfield(poSFDefn,TRUE); } CSLDestroy(papszSubfieldNames); returnTRUE; } 例如: 共定义了12个字段的格式,分别为A (2),I(10),3A,A(3),4R,2A。 定义的子字段存入papoSubfields中,而papoSubfields定义为: DDFSubfieldDefn**papoSubfields; 注意: 每一个字段对应一个对象,存入DDFModule类中的 DDFFieldDefn**papoFieldDefns;数组。 而每一个子字段DDFSubfieldDefn**papoSubfields又存入字段类DDFFieldDefn中。 ApplyFormats功能为将字段区的格式域应用于各子字段中。 intDDFFieldDefn: : ApplyFormats() { char*pszFormatList; char**papszFormatItems; if(strlen(_formatControls)<2||_formatControls[0]! ='(' ||_formatControls[strlen(_formatControls)-1]! =')') { CPLError(CE_Failure,CPLE_AppDefined,"Formatcontrolsfor`%s'fieldmissingbrackets: %s\n",pszTag,_formatControls); returnFALSE; } pszFormatList=ExpandFormat(_formatControls); //展开格式控制,如3A,展开后为: A,A,A papszFormatItems= CSLTokenizeStringplex(pszFormatList,",",FALSE,FALSE); 将展开后的格式控制字符串,变成单个格式控制组成的指针.如 “(A,A,A,B10,F4)〞 那么指针分别指向: A,A,A,B10,F4各单项 CPLFree(pszFormatList); intiFormatItem; for(iFormatItem=0;papszFormatItems[iFormatItem]! =NULL; iFormatItem++) { constchar*pszPastPrefix; pszPastPrefix=papszFormatItems[iFormatItem]; while(*pszPastPrefix>='0'&&*pszPastPrefix<='9') pszPastPrefix++; if(iFormatItem>=nSubfieldCount) { CPLError(CE_Warning,CPLE_AppDefined,"格式项与子字段项不等`%s'.\n",pszTag); break; } if(! papoSubfields[iFormatItem]->SetFormat(pszPastPrefix)) returnFALSE; } CSLDestroy(papszFormatItems); if(iFormatItem { CPLError(CE_Failure,CPLE_AppDefined, "Gotlessformatsthansubfieldsforfield`%s',\n", pszTag); returnFALSE; } 判断该字段是否为定长, nFixedWidth=0; for(inti=0;i { if(papoSubfields[i]->GetWidth()==0) { nFixedWidth=0; 只要有一个子字段不定长时,那么该字段不定长,即nFixedWidth=0; break; } else nFixedWidth+=papoSubfields[i]->GetWidth(); } returnTRUE; } 二、DR构造 1.文件头区 24个字节,容如下表 记录长度是指DR的总长度. 3.记录区 与DDR一样 3.字段区 与DDR一样 DR程序分析: 在DR区每次读入一条记录,存入DDFModule类的poRecord。 而poRecord类型为: DDFRecord*poRecord; 注意: 每一个DR读入后,即开场处理,并未保存poRecord; 在每次DR的读入过程中,首先判断上一次读入的DR文件头是否要重要使用,假设否,那么先读入该DR的文件头。 if(! nReuseHeader) { return(ReadHeader()); } 其中,nReuseHeader在上一个DR的文件头中定义。 if(_leaderIden=='R')nReuseHeader=TRUE; DR中的数据存入DDFRecord类的pachData中。 本DR的字段个数存入DDFRecord类中的nFieldCount。 DR中的字段存入paoFields=newDDFField[nFieldCount]中; 初始化paoFields后得到各字段的数据、长度,并在DDFModule类中定义的 DDFFieldDefn**papoFieldDefns;找到对应项,取到相应的格式。 然后,调用CParseS57_VC6Doc中的函数: ViewRecordField来解析本DR中的全部字段。 得到物标的特征属性数据和空间属性数据。 DDFFieldDefn*poFieldDefn=poModule->FindFieldDefn(szTag); 读DR时,调用oModule.ReadRecord().每个DR对应一个oModule.ReadRecord(). 在oModule.ReadRecord()中,先读出文件头区,然后读出记录区,每条记录对应一个字段.然后调用ViewRecordField来解析该字段对应的数据. while((poRecord=oModule.ReadRecord())! =NULL) { //debuginfo("DDFRecordstart\n"); for(intiField=0;iField { DDFField*poField=poRecord->GetField(iField); ViewRecordField(poField); nFieldCount++; } nRecordCount++; } 字段数据解析函数 voidCParseS57Doc: : ViewRecordField(DDFField*poField) { intnBytesRemaining; constchar*pachFieldData; DDFFieldDefn*poFieldDefn=poField->GetFieldDefn(); charstr[300]; if((strncmp(poFieldDefn->GetName(),"VRID",4)==0)||(strncmp(poFieldDefn->GetName(),"FRID",4)==0)) {//为空间数据就打印,并赋m_datatype值 m_datatype=NEED_TYPE; } elseif(strncmp(poFieldDefn->GetName(),"ATTF",4)==0) { m_datatype=OBJT_TYPE|SUB3_TYPE; } elseif(strncmp(poFieldDefn->GetName(),"FSPT",4)==0) { m_datatype=OBJT_TYPE|SUB4_TYPE; } pachFieldData=poField->GetData(); nBytesRemaining=poField->GetDataSize(); intiRepeat; for(iRepeat=0;iRepeat { intiSF; for(iSF=0;iSF { DDFSubfieldDefn*poSFDefn=oFieldDefn->GetSubfield(iSF); intnBytesConsumed; nBytesConsumed=ViewSubfield(poSFDefn,pachFieldData,nBytesRemaining); nBytesRemaining-=nBytesConsumed; pachFieldData+=nBytesConsumed; } } } 如果字段是以*开头,且是定长,那么可能有该字段重复数据 .poField->GetRepeatCount() 重复个数为=数据总长度/字段的长度(该字段必须是定长) 如果有子字段,那么调用ViewSubfield()函数来解析子字段数据. 读取字段数据,和子字段数据时,按特殊标识符(FT=30,UT=31)和定长来读取相应的数据. 每一个DR描述一种物标,包括: DSID、DSPM、FRID、VRID。 其中: DSID描述该文件的总体信息;DSPM描述该文件中的相关参数;FRID有多个,每个描述一种物标;VRID也有多个,每个可描述: 离散点〔SG2D、SG3D〕,或连接点,或一条边〔边可能只有起点、终点,由VRPT确定〔该DR形式为: 0001、VRID、VRPT〕,边可能由起点、终点、中间点组成〔该DR形式为: 0001、VRID、VRPT、*SG2D〕,*表示重复多个〕。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- S57 文件 结构 分析