S57-文件结构分析
更新时间:2023-03-08 05:14:25 阅读量: 综合文库 文档下载
- s57文件解析推荐度:
- 相关推荐
S57文件存储结构
一、 DDR结构
DDR中定义了文件的总体信息, 包括文件名, 字段名, 字段类型, 字段格式和长度, 字段间的关系, 及子字段.
1. 文件头区
24个字节, 内容如下表
记录长度是指DDR的总长度.
2. 记录区
记录区从第25个字节开始, 直到字节值=30为止. 30称为字段终结符(FT=30).
每个记录的长度由: 文件头区中的, 字段长度大小, 字段位置大小, 字段标识的大小之和决定.
每个记录描述一个字段的基本信息(名称、长度、起始位置). 每个记录是定长的.
3.字段区
记录区中的每一条记录对应一个字段,然后在字段描述区进一步给出字段的具体信息。每个字段的描述信息之间由字段终结符(FT 30)隔开。每个字段的描述信息内部不同部分由单元终结符(UT=31)隔开。其中每个字段描述信息的第一部分为字段的控制信息, 共9个字节组成。
DDR的第一个字段为控制字段,字段名为\(地址为:目录区后的第一个字节(文件头+
目录区的长度))
控制字段给出了文件名、及全部字段的结构信息。
例如:如下控制字段数据可生成对应的字段结构图
DDR的其余字段为数据描述字段,(地址为:目录区后的第一个字节+该字段的偏移量)。
例如:如下的字段描述字段为
4.程序实现
S57-文件对应的DDFModule类,在该类中读入DDR信息。其中,DDR文件头存入achLeader中。
char achLeader[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 );
void DDFModule::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() ) return FALSE;
if( !ApplyFormats() ) return FALSE; }
其中,BuildSubfields定义如下:
int DDFFieldDefn::BuildSubfields() {
char **papszSubfieldNames;
const char *pszSublist = _arrayDescr; //字段描述区字符,在Initialize中定义 if( pszSublist[0] == '*' ) {
bRepeatingSubfields = TRUE; pszSublist++; }
papszSubfieldNames = CSLTokenizeStringComplex( pszSublist, \, FALSE, FALSE ); int nSFCount = CSLCount( papszSubfieldNames ); for( int iSF = 0; iSF < nSFCount; iSF++ ) {
DDFSubfieldDefn *poSFDefn = new DDFSubfieldDefn; poSFDefn->SetName( papszSubfieldNames[iSF] ); AddSubfield( poSFDefn, TRUE ); }
CSLDestroy( papszSubfieldNames ); return TRUE; }
例如:
共定义了12个字段的格式,分别为A(2),I(10),3A,A(3),4R,2A。
定义的子字段存入papoSubfields中,而papoSubfields定义为:
DDFSubfieldDefn **papoSubfields;
注意:每一个字段对应一个对象,存入DDFModule类中的
DDFFieldDefn **papoFieldDefns;数组内。
而每一个子字段DDFSubfieldDefn **papoSubfields又存入字段类DDFFieldDefn中。
ApplyFormats功能为将字段区内的格式域应用于各子字段中。
int DDFFieldDefn::ApplyFormats() {
char *pszFormatList; char **papszFormatItems;
if( strlen(_formatControls) < 2 || _formatControls[0] != '(' || _formatControls[strlen(_formatControls)-1] != ')' ) {
CPLError( CE_Failure, CPLE_AppDefined, \controls for `%s'
field missing brackets:%s\\n\, pszTag, _formatControls );
return FALSE; }
pszFormatList = ExpandFormat( _formatControls ); //展开格式控制, 如3A, 展开后为: A,A,A papszFormatItems =
CSLTokenizeStringComplex(pszFormatList, \, FALSE, FALSE ); 将展开后的格式控制字符串, 变成单个格式控制组成的指针.如 “(A,A,A,B10,F4)”
则指针分别指向: A,A,A,B10,F4各单项 CPLFree( pszFormatList ); int iFormatItem;
for( iFormatItem = 0; papszFormatItems[iFormatItem] != NULL; iFormatItem++ ) {
const char *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) ) return FALSE; }
CSLDestroy( papszFormatItems );
if( iFormatItem < nSubfieldCount ) {
CPLError( CE_Failure, CPLE_AppDefined,
\, pszTag ); return FALSE; }
判断该字段是否为定长, nFixedWidth = 0;
for( int i = 0; i < nSubfieldCount; i++ ) {
if( papoSubfields[i]->GetWidth() == 0 ) {
nFixedWidth = 0;
只要有一个子字段不定长时, 则该字段不定长,即nFixedWidth = 0; break; } else
nFixedWidth += papoSubfields[i]->GetWidth(); }
return TRUE; }
二、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 = new DDFField[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(\start@@@@@@@@@@@@@@@@@@@@@@@@@@@@\\n\
for( int iField = 0; iField < poRecord->GetFieldCount(); iField++ ) {
DDFField *poField = poRecord->GetField( iField );
ViewRecordField( poField );
nFieldCount++; }
nRecordCount++; }
字段数据解析函数
void CParseS57Doc::ViewRecordField(DDFField * poField) {
int nBytesRemaining; const char *pachFieldData;
DDFFieldDefn *poFieldDefn = poField->GetFieldDefn(); char str[300];
if ((strncmp(poFieldDefn->GetName(), \, 4) == 0)||(strncmp(poFieldDefn->GetName(), \, 4)==0)) { //为空间数据就打印,并赋m_datatype值
m_datatype=NEED_TYPE; }
else if (strncmp(poFieldDefn->GetName(), \, 4) == 0) {
m_datatype=OBJT_TYPE|SUB3_TYPE; }
else if(strncmp(poFieldDefn->GetName(), \, 4) == 0) {
m_datatype=OBJT_TYPE|SUB4_TYPE; }
pachFieldData = poField->GetData();
nBytesRemaining = poField->GetDataSize(); int iRepeat;
for( iRepeat = 0; iRepeat < poField->GetRepeatCount(); iRepeat++ ) {
int iSF;
for( iSF = 0; iSF < poFieldDefn->GetSubfieldCount(); iSF++ ) {
DDFSubfieldDefn *poSFDefn = oFieldDefn->GetSubfield( iSF ); int nBytesConsumed; 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),*表示重复多个)。
正在阅读:
S57-文件结构分析03-08
逻辑学模拟试题一09-26
第六章平面直角坐标系复习学案03-08
申请人思想品德鉴定表填写模板01-01
2015全国中考分类解析—光现象03-12
宏观经济学作业09-19
小学六年级上册数学六单元单元备课05-25
钢箱梁涂装技术交底书05-31
知识作文之专业知识读书笔记05-05
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 结构
- 文件
- 分析
- 57
- 2011年度小学六年级英语提高毕业成绩计划
- 武鸣县2013年第十三期国有建设用地使用权
- 关于户县当前城市建设管理的几点思考
- 探索物质变化—教案 - 图文
- 路灯管理所创建区级文明单位情况汇报
- 关于转发《关于做好2007年大学生志愿服务西部计划志愿者招募选拔
- 组织行为学-在线作业 - e
- 最新精品作文:一次独特的体验 - 450字作文
- 学校举办者变更
- 聋校五年级下期教学计划
- 2018年中国户外家具行业调研分析及市场报告目录
- MPV行业现状及发展趋势分析报告
- 重庆市人民政府关于綦江区划调整
- 基于DS1302与LCD1602的电子日历时钟的设计与实现
- 国际贸易概论试题3答案
- 年产20万吨煤制甲醇生产工艺毕业设计
- 人教班三年级上册各单元复习重点
- 2012济南中考语文市中区一模试卷
- 港西污水处理厂管理手册2016.05.31 - 图文
- 2011年全市绿色生态医院建设检查标准记录(定)2