S57文件结构分析.docx

上传人:b****8 文档编号:11173880 上传时间:2023-02-25 格式:DOCX 页数:13 大小:293.53KB
下载 相关 举报
S57文件结构分析.docx_第1页
第1页 / 共13页
S57文件结构分析.docx_第2页
第2页 / 共13页
S57文件结构分析.docx_第3页
第3页 / 共13页
S57文件结构分析.docx_第4页
第4页 / 共13页
S57文件结构分析.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

S57文件结构分析.docx

《S57文件结构分析.docx》由会员分享,可在线阅读,更多相关《S57文件结构分析.docx(13页珍藏版)》请在冰豆网上搜索。

S57文件结构分析.docx

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;iFieldGetFieldCount();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;iRepeatGetRepeatCount();iRepeat++)

{

intiSF;

for(iSF=0;iSFGetSubfieldCount();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〕,*表示重复多个〕。

 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 经济学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1