[转]多谱勒雷达产品格式
来源:怀化气象论坛 作者:dktanqx 链接:http://soft666.com/bbs/read.php?tid-43383.html
多谱勒雷达产品格式
一个人在外地真无聊!给大伙贴我已经翻译出来的多谱勒雷达产品格式。有兴趣的请与说明文档对照着看吧。具体的说明文档在www.cinrad.com有下。
typedef struct MESSAGEHEADER
{
unsigned short MessageCode; //表2
unsigned short DateOfMessage; //儒略历日期,从1970.1.1起,1 到 32,767
unsigned char TimeofMessage[4]; //0 to 86,399
unsigned char LengthofMessage[4]; //18 to 409856
unsigned short SourceID; //0 to 999
unsigned short DestinationID; //0 to 999
unsigned short NumberBlocks; //1 to 51
}MessageHeader;
以上是第一个文件头,应该还看得明白吧。
typedef struct MESSAGEHEADER
{
unsigned short MessageCode; //表2
unsigned short DateOfMessage; //儒略历日期,从1970.1.1起,1 到 32,767
unsigned char TimeofMessage[4]; //0 to 86,399
unsigned char LengthofMessage[4]; //18 to 409856
unsigned short SourceID; //0 to 999
unsigned short DestinationID; //0 to 999
unsigned short NumberBlocks; //1 to 51
}MessageHeader;
以上是第一个文件头,应该还看得明白吧。
=======================================================
typedef struct PRODUCTDESCRIPTION //p10,p17,len=102
{
short BlockDivider; //0xFFFF
unsigned char LatitudeofRadar[4]; //-90 to +90,精度0.001
unsigned char LongitudeofRadar[4]; //-180 to +180 ,精度0.001
short HeightofRadar; //-100 to +11000,单位英尺
short ProductCode; //16 to 131,-16 to -131
unsigned short OperationalMode; //0-2:0 = Maintenance,1 = Clean Air,2 = Precipitation/Severe Weather
unsigned short VolumeCoveragePattern; //1 to 767,体扫覆盖方式VCP,RDA volume coverage pattern for the scan strategy being used
short SequenceNumber; //-13,0 to 32767,顺序号,Sequence number of the 0 to 32767 request that generated the product (Refer to Figure 3-3). For products generated by an alert Condition, sequence number = -13
unsigned short VolumeScanNumber; //1-80,Counter, recycles to one (1) every 80 volume scans
unsigned short VolumeScanDate; //1-32767,从1970年1月1日算起
unsigned char VolumeScanStartTime[4]; //0-86399
unsigned short ProductGenerationDate; //1 to 32767
unsigned char ProductGenerationTime[4]; //0 to 86399
short ProductDependent_P1; //见表5,第22页 //34
short ProductDependent_P2; //见表5
unsigned short ElevationNumber; //1-20,体扫时的仰角数
short ProductDependent_P3; //见表5
unsigned short DataLevelThreshold[16]; //见19页注意
short ProductDependent_P4; //见表5
short ProductDependent_P5; //见表5
short ProductDependent_P6; //见表5
short ProductDependent_P7; //见表5
short ProductDependent_P8; //见表5
short ProductDependent_P9; //见表5
short ProductDependent_P10; //见表5
unsigned short NumberOfMaps; //0-17,或者Version(0-255)和Spot Blank(0-1),当MSG为地图数据时,为地图数,当MSG为产品数据时,高位是版本,低位是Spot Blank开关,1开,0关
unsigned char OffsetToSymb0logy[4]; //0 to 80000
unsigned char OffsetToGraphic[4]; //0 to 80000
unsigned char OffsetToTabular[4]; //0 to 80000
}ProductDescription;
第二个文件头,说明一下:
DataLevelThreshold[16]是临界值,也就是雷达图上色标旁的那些数字,要翻译哟,详细的说明在文档的19页。
ProductDependent_P1-10是有关的详细信息(文档第22页表格), 如仰角,最大值之类。对每一种产品, 这10个值的意义是不同的,表格中的Hword #代表该项在文件中的双字节位置,如ProductDependent_P1是27,ProductDependent_P2是28,ProductDependent_P3是30,慢慢对照看会明白的。
对所有的产品,上面两个头是固定的,下面的三个结构则不一定。
{
short BlockDivider; //0xFFFF
unsigned char LatitudeofRadar[4]; //-90 to +90,精度0.001
unsigned char LongitudeofRadar[4]; //-180 to +180 ,精度0.001
short HeightofRadar; //-100 to +11000,单位英尺
short ProductCode; //16 to 131,-16 to -131
unsigned short OperationalMode; //0-2:0 = Maintenance,1 = Clean Air,2 = Precipitation/Severe Weather
unsigned short VolumeCoveragePattern; //1 to 767,体扫覆盖方式VCP,RDA volume coverage pattern for the scan strategy being used
short SequenceNumber; //-13,0 to 32767,顺序号,Sequence number of the 0 to 32767 request that generated the product (Refer to Figure 3-3). For products generated by an alert Condition, sequence number = -13
unsigned short VolumeScanNumber; //1-80,Counter, recycles to one (1) every 80 volume scans
unsigned short VolumeScanDate; //1-32767,从1970年1月1日算起
unsigned char VolumeScanStartTime[4]; //0-86399
unsigned short ProductGenerationDate; //1 to 32767
unsigned char ProductGenerationTime[4]; //0 to 86399
short ProductDependent_P1; //见表5,第22页 //34
short ProductDependent_P2; //见表5
unsigned short ElevationNumber; //1-20,体扫时的仰角数
short ProductDependent_P3; //见表5
unsigned short DataLevelThreshold[16]; //见19页注意
short ProductDependent_P4; //见表5
short ProductDependent_P5; //见表5
short ProductDependent_P6; //见表5
short ProductDependent_P7; //见表5
short ProductDependent_P8; //见表5
short ProductDependent_P9; //见表5
short ProductDependent_P10; //见表5
unsigned short NumberOfMaps; //0-17,或者Version(0-255)和Spot Blank(0-1),当MSG为地图数据时,为地图数,当MSG为产品数据时,高位是版本,低位是Spot Blank开关,1开,0关
unsigned char OffsetToSymb0logy[4]; //0 to 80000
unsigned char OffsetToGraphic[4]; //0 to 80000
unsigned char OffsetToTabular[4]; //0 to 80000
}ProductDescription;
第二个文件头,说明一下:
DataLevelThreshold[16]是临界值,也就是雷达图上色标旁的那些数字,要翻译哟,详细的说明在文档的19页。
ProductDependent_P1-10是有关的详细信息(文档第22页表格), 如仰角,最大值之类。对每一种产品, 这10个值的意义是不同的,表格中的Hword #代表该项在文件中的双字节位置,如ProductDependent_P1是27,ProductDependent_P2是28,ProductDependent_P3是30,慢慢对照看会明白的。
对所有的产品,上面两个头是固定的,下面的三个结构则不一定。
===========================================================
格式中的变量的单位与公用的的单位不同:长度(海泼)用英尺,距离用海里,速度用海里/小时,这些都要转换成常用的单位。
另外,其数据的写入是与WINXP相反的,即WINDOW在写入时是高位在后,低位在前,而它则相反,因此在读入变量后要将变量的高低位倒过来,所以我对4字节的long型量用unsigned char TimeofMessage[4]这样来定义,然后再long nTimeofMessage=MSGheader.TimeofMessage[0]<<24|MSGheader.TimeofMessage[1]<<16|
MSGheader.TimeofMessage[2]<<8|MSGheader.TimeofMessage[3];
MESSAGEHEADER
PRODUCTDESCRIPTION
PRODUCTSYMBOLOGY
GRAPHICALPHANUMERIC
TABULARALPHANUMERIC
以上是这些结构的排列顺序,前两个是所产品格式都有的,后面的三个则要视产品而定,如果有的话,必定是按这个顺序排列的。
下面讲第三部分,也是最主要的部分PRODUCTSYMBOLOGY
另外,其数据的写入是与WINXP相反的,即WINDOW在写入时是高位在后,低位在前,而它则相反,因此在读入变量后要将变量的高低位倒过来,所以我对4字节的long型量用unsigned char TimeofMessage[4]这样来定义,然后再long nTimeofMessage=MSGheader.TimeofMessage[0]<<24|MSGheader.TimeofMessage[1]<<16|
MSGheader.TimeofMessage[2]<<8|MSGheader.TimeofMessage[3];
MESSAGEHEADER
PRODUCTDESCRIPTION
PRODUCTSYMBOLOGY
GRAPHICALPHANUMERIC
TABULARALPHANUMERIC
以上是这些结构的排列顺序,前两个是所产品格式都有的,后面的三个则要视产品而定,如果有的话,必定是按这个顺序排列的。
下面讲第三部分,也是最主要的部分PRODUCTSYMBOLOGY
============================================================
PRODUCTSYMBOLOGY的开始是以下的一个结构
typedef struct PRODUCTSYMBOLOGY///////////////////p14,p20
{
short BlockDivider; //0xFFFF
short BlockID; //=1
unsigned char LengthOfBlock[4]; //1-80000 ,Length of block in bytes (includes preceding divider and block id)
short NumberOfLayers; //1-15 ,Number of data layers contained in this block ( 见注意2)
// DisplayDataPacket Packets[NumberOfLayers]; SEE FIGURES 3 - 6 THRU 3 - 14
}ProductSymbology;
BlockID=1,表示这是PRODUCTSYMBOLOGY
NumberOfLayers 表示有几个数据块,要循环读。但好像只有弱回波区WER(=7)和剖面(反射率)RCS(=2)(不知道VCS,SCS是多少,我们这里雷达没生成这两种产品),其它都是1。
下面是图像块,先是一个BlockDivider;然后是四位长度LengthOfDataLayer[4],随后就是具体的图像结构。
{
BlockDivider
LengthOfDataLayer[4]
具体的图像结构
}
这样的结构有NumberOfLayers个,不知我说清楚了没有。
下面计具体的图像结构。
typedef struct PRODUCTSYMBOLOGY///////////////////p14,p20
{
short BlockDivider; //0xFFFF
short BlockID; //=1
unsigned char LengthOfBlock[4]; //1-80000 ,Length of block in bytes (includes preceding divider and block id)
short NumberOfLayers; //1-15 ,Number of data layers contained in this block ( 见注意2)
// DisplayDataPacket Packets[NumberOfLayers]; SEE FIGURES 3 - 6 THRU 3 - 14
}ProductSymbology;
BlockID=1,表示这是PRODUCTSYMBOLOGY
NumberOfLayers 表示有几个数据块,要循环读。但好像只有弱回波区WER(=7)和剖面(反射率)RCS(=2)(不知道VCS,SCS是多少,我们这里雷达没生成这两种产品),其它都是1。
下面是图像块,先是一个BlockDivider;然后是四位长度LengthOfDataLayer[4],随后就是具体的图像结构。
{
BlockDivider
LengthOfDataLayer[4]
具体的图像结构
}
这样的结构有NumberOfLayers个,不知我说清楚了没有。
下面计具体的图像结构。
==================================================
图像分以下几种:
1 Radial Image
2 Raster Image
3 Linked Contour Vectors
4 Geographic and Non-geographic Alpha、
5 ...
但最主要的是1和2,先讲1:
基本反射率R,基本速度V,基本谱宽SW,1小时累积降水OHP,3小时累积降水THP,风暴总累积降水STP和产品号大于等于110的产品,其图像都是1(Radial Image,以下用基本反射率R统指)
typedef struct RADIALDATAPACKET
{
short nFlag; //0xAF1F,这标志这是Radial Image
short IndexofFirstRangeBin; //0-460
short NumberofRangeBins; //1-460
short ICenterofSweep; //
short JCenterofSweep; //
short ScaleFactor; //0.001-8.000
short NumberofRadials; //1-460
}RadialDataPacket;//格式文档第48页
R是以一个个扇形写入的,每一个扇形有开始角度,扇形的张角,每个扇形有多少个范围环,每个范围环有开始距离,结束距离。唉,这样写不知大家明白否,当初我是研究了几天才明白!
IndexofFirstRangeBin是扇形的环的开始点,一般从圆心开始,=0
NumberofRangeBins是表示有多少个范围环组成一个扇形。
ICenterofSweep和JCenterofSweep是圆心坐标,都是(400,400),只有OHP,THP,STP不是,找不到原因,我不管它,统统以(400,400)代替
ScaleFactor表示每个范围环的象素数,举个例,如果某个范围环从10开始,15结束,那么这个范围环的厚度是6*ScaleFactor个象素
NumberofRadials表示有多少个扇形组成一个圆,即雷达图像。
下面要循环读一个个范围环和一个个扇形。(NumberofRangeBins个范围环组成一个扇形)
开始两个字节N表示这个扇形的图像有多少个双字节组成
再两个字节A表示这个扇形的开始角度
再两个字节B表示这个扇形的张度(可以算出,这个扇形有N*2+6个字节组成)
再N*2个字节就是一个个范围环,每个字节的高位表示范围环的个数,低字节表示这些范围环的颜色序号,即在色标中的索引号。举个例吧:
如果读出值是245(16进制是F5),表示这是15个范围环(用X个表示),其颜色序号都是6
这个扇形所有的X的和应该是NumberofRangeBins,NumberofRangeBins*ScaleFactor就是雷达图的半径(一般=400)。
唉,我自己看了都觉得没有讲清楚,大伙慢慢研究吧!
1 Radial Image
2 Raster Image
3 Linked Contour Vectors
4 Geographic and Non-geographic Alpha、
5 ...
但最主要的是1和2,先讲1:
基本反射率R,基本速度V,基本谱宽SW,1小时累积降水OHP,3小时累积降水THP,风暴总累积降水STP和产品号大于等于110的产品,其图像都是1(Radial Image,以下用基本反射率R统指)
typedef struct RADIALDATAPACKET
{
short nFlag; //0xAF1F,这标志这是Radial Image
short IndexofFirstRangeBin; //0-460
short NumberofRangeBins; //1-460
short ICenterofSweep; //
short JCenterofSweep; //
short ScaleFactor; //0.001-8.000
short NumberofRadials; //1-460
}RadialDataPacket;//格式文档第48页
R是以一个个扇形写入的,每一个扇形有开始角度,扇形的张角,每个扇形有多少个范围环,每个范围环有开始距离,结束距离。唉,这样写不知大家明白否,当初我是研究了几天才明白!
IndexofFirstRangeBin是扇形的环的开始点,一般从圆心开始,=0
NumberofRangeBins是表示有多少个范围环组成一个扇形。
ICenterofSweep和JCenterofSweep是圆心坐标,都是(400,400),只有OHP,THP,STP不是,找不到原因,我不管它,统统以(400,400)代替
ScaleFactor表示每个范围环的象素数,举个例,如果某个范围环从10开始,15结束,那么这个范围环的厚度是6*ScaleFactor个象素
NumberofRadials表示有多少个扇形组成一个圆,即雷达图像。
下面要循环读一个个范围环和一个个扇形。(NumberofRangeBins个范围环组成一个扇形)
开始两个字节N表示这个扇形的图像有多少个双字节组成
再两个字节A表示这个扇形的开始角度
再两个字节B表示这个扇形的张度(可以算出,这个扇形有N*2+6个字节组成)
再N*2个字节就是一个个范围环,每个字节的高位表示范围环的个数,低字节表示这些范围环的颜色序号,即在色标中的索引号。举个例吧:
如果读出值是245(16进制是F5),表示这是15个范围环(用X个表示),其颜色序号都是6
这个扇形所有的X的和应该是NumberofRangeBins,NumberofRangeBins*ScaleFactor就是雷达图的半径(一般=400)。
唉,我自己看了都觉得没有讲清楚,大伙慢慢研究吧!
==================================================
本来直上传一张图片来说明一下,不知道怎么传,只好作罢。
在所的产品格式中,Radial Image是最复杂的,不仅是开始理解难,而且即使明白了,在画图的时候也不好处理。这种格式本来就不好画,还要要考虑到在放大缩小图片时不能使图片失真的问题。关于画Radial Image图像,我至今都没有完全解决好。我画的图放大缩小没有失真,但时间长(即使是在内存中操作),复杂一点的图要1.5秒左右,一点都不爽,不知道大家能不能想到好的方法。
下面讲2。
组合反射率CR,回波顶ET,剖面,弱回波区WER,垂直积分液态含水量VIL,分层组合反射率平均值LRA,分层组合反射率最大值LRM,综合切变CS等等产品格式都是2(以CR统指)。
CR格式比较简单。
typedef struct RASTERDATAPACKET //第50,51
{
// short nFlag1; //0xBA0F或0xBA07
short nFlag2; //0x80000
short nFlag3; //0x00C0
short ICoordinateStart; //
short JCoordinateStart; //
unsigned short XScaleINT; //
short XScaleFractional; //
unsigned short YScaleINT; //
short YScaleFractional; //
unsigned short NumberofRows; //
unsigned short PackingDescriptor; //=2
}RasterDataPacket;
前面6字节是标志
XScaleINT和YScaleINT分别是XY方向的放大倍数
XScaleFractional和YScaleFractional是保留的
NumberofRows是行数,NumberofRows*YScaleFractional图像的总行数
PackingDescriptor==2
ICoordinateStart和JCoordinateStart是开始的IJ坐标
R图像是按从左至右,从上到下的顺序画的。
头后面便是图像数据块
开始2字节表示这一行有N字节(不包括这2字节,这一行总字节是N+2)
然后就可循环读取一字节,每个字节的高位表示M,低字节表示颜色序号,即在色标中的索引号。举个例吧:
如果读出值是245(16进制是F5,即高位是M=15,低位是5),表示在(X0,Y0,X0+M*XScaleINT,Y0+YScaleINT)这个区域里,其颜色序号都是6(比如说是RGB( 0,234, 0))
上面的区域中,X0是本字节前的报有字节的M之和*XScaleINT加ICoordinateStart,Y0是行数(NumberofRows中的一个)*YScaleINT+JCoordinateStart
明白否?
在所的产品格式中,Radial Image是最复杂的,不仅是开始理解难,而且即使明白了,在画图的时候也不好处理。这种格式本来就不好画,还要要考虑到在放大缩小图片时不能使图片失真的问题。关于画Radial Image图像,我至今都没有完全解决好。我画的图放大缩小没有失真,但时间长(即使是在内存中操作),复杂一点的图要1.5秒左右,一点都不爽,不知道大家能不能想到好的方法。
下面讲2。
组合反射率CR,回波顶ET,剖面,弱回波区WER,垂直积分液态含水量VIL,分层组合反射率平均值LRA,分层组合反射率最大值LRM,综合切变CS等等产品格式都是2(以CR统指)。
CR格式比较简单。
typedef struct RASTERDATAPACKET //第50,51
{
// short nFlag1; //0xBA0F或0xBA07
short nFlag2; //0x80000
short nFlag3; //0x00C0
short ICoordinateStart; //
short JCoordinateStart; //
unsigned short XScaleINT; //
short XScaleFractional; //
unsigned short YScaleINT; //
short YScaleFractional; //
unsigned short NumberofRows; //
unsigned short PackingDescriptor; //=2
}RasterDataPacket;
前面6字节是标志
XScaleINT和YScaleINT分别是XY方向的放大倍数
XScaleFractional和YScaleFractional是保留的
NumberofRows是行数,NumberofRows*YScaleFractional图像的总行数
PackingDescriptor==2
ICoordinateStart和JCoordinateStart是开始的IJ坐标
R图像是按从左至右,从上到下的顺序画的。
头后面便是图像数据块
开始2字节表示这一行有N字节(不包括这2字节,这一行总字节是N+2)
然后就可循环读取一字节,每个字节的高位表示M,低字节表示颜色序号,即在色标中的索引号。举个例吧:
如果读出值是245(16进制是F5,即高位是M=15,低位是5),表示在(X0,Y0,X0+M*XScaleINT,Y0+YScaleINT)这个区域里,其颜色序号都是6(比如说是RGB( 0,234, 0))
上面的区域中,X0是本字节前的报有字节的M之和*XScaleINT加ICoordinateStart,Y0是行数(NumberofRows中的一个)*YScaleINT+JCoordinateStart
明白否?