多普勒天气雷达的体扫产品处理代码。
包含RasterImage.java、RasterImageBlock.java、RasterProductBlock.java三个类。
由SymbologyImage.java类判断产品为Symbology且特征码为BA0F或BA07时调用。
RasterImage.java
001 /**
002 * PACKAGE : cma.gmb.doppler
003 * FILENAME : RasterImage.java
004 * DESCRIPTION : 处理多普勒雷达产品数据(格栅产品Raster)
005 * AUTHOR : 刘泽军
006 * EMAIL : BJ0773@gmail.com
007 * Date : 2007-06-02 23:52:38
008 * Update : 2007-06-13 从SymbologyImage.java中独立出来
009 * Reference : 《National Climatic Data Center DATA DOCUMENTATION FOR TD7000 -
010 * TD7599 NEXRAD LEVEL III》
011 *
012 */
013
014 package cma.gmb.doppler;
015
016 import java.io.*;
017 import java.awt.*;
018
019 import cma.common.dataio.*;
020 import cma.common.projection.*;
021 import cma.micaps.diamond.*;
022 import cma.gmb.doppler.datatype.*;
023
024 public class RasterImage {
025 //外部传入的数据
026 public MessageHeaderBlock messageHeaderBlock;
027 public ProductDescriptionBlock productDescriptionBlock;
028 public ProductSymbologyBlock productSymbologyBlock;
029 public ProductSymbologyLayerBlock productSymbologyLayerBlock;
030 //需要读取的数据
031 public RasterProductBlock rasterProductBlock;
032 public RasterImageBlock [] rasterImageBlock;
033
034 public static Color [] levels = {
035 new Color ( 0 , 0 , 0 ) , new Color ( 0 , 0 , 246 ) , new Color ( 1 , 159 , 246 ) , new Color ( 0 , 236 , 236 ) ,
036 new Color ( 1 , 255 , 0 ) , new Color ( 0 , 200 , 0 ) , new Color ( 1 , 144 , 0 ) , new Color ( 255 , 255 , 0 ) ,
037 new Color ( 231 , 192 , 0 ) , new Color ( 255 , 144 , 0 ) , new Color ( 254 , 0 , 0 ) , new Color ( 214 , 0 , 0 ) ,
038 new Color ( 192 , 0 , 0 ) , new Color ( 255 , 0 , 250 ) , new Color ( 174 , 144 , 240 ) , new Color ( 255 , 255 , 255 )
039 } ;
040
041 /**
042 * 功能:构造函数
043 * 参数:
044 * 无
045 * 返回值:
046 * 无
047 */
048 public RasterImage () {
049 }
050
051 /**
052 * 功能:读取多普勒栅格数据Raster Image,不包括文件头信息,注意在调用前先定位好偏移量
053 * 参数:
054 * fin - 随机访问的文件对象
055 * 返回值:
056 * 是否成功
057 */
058 public boolean read ( RandomAccessFile fin ) throws Exception {
059
060 if ( ! "BA0F" .equalsIgnoreCase ( productSymbologyLayerBlock.PacketCode ) &&
061 ! "BA07" .equalsIgnoreCase ( productSymbologyLayerBlock.PacketCode ) ) { //非栅格数据 Raster Image
062 return ( false ) ;
063 }
064 boolean ok = false ;
065 rasterProductBlock = new RasterProductBlock () ;
066 ok = rasterProductBlock.read ( fin ) ;
067 if ( rasterProductBlock.NumberOfRows > 0 ) {
068 rasterImageBlock = new RasterImageBlock [ rasterProductBlock.NumberOfRows ] ;
069 for ( int i= 0 ;i<rasterProductBlock.NumberOfRows;i++ ) {
070 rasterImageBlock [ i ] = new RasterImageBlock () ;
071 ok = ok && rasterImageBlock [ i ] .read ( fin ) ;
072 }
073 }
074 return ( ok ) ;
075 }
076
077 /**
078 * 2007-06-04增加,并在相关的类中增加 read(InputStream fin) 方法
079 *
080 * 功能:从数据流中读取多普勒栅格数据Raster,主要是考虑直接从 .tar.gz 中读取
081 * 参数:
082 * fin - InputStream,注意不能使用 fin.close() 方法,因为在函数外部可能还需要继续从 fin 读数据
083 * 返回值:
084 * 是否成功
085 */
086 public boolean read ( InputStream fin ) throws Exception {
087
088 if ( ! "BA0F" .equalsIgnoreCase ( productSymbologyLayerBlock.PacketCode ) &&
089 ! "BA07" .equalsIgnoreCase ( productSymbologyLayerBlock.PacketCode ) ) { //非栅格数据 Raster Image
090 return ( false ) ;
091 }
092 boolean ok = false ;
093 rasterProductBlock = new RasterProductBlock () ;
094 ok = rasterProductBlock.read ( fin ) ;
095 if ( rasterProductBlock.NumberOfRows > 0 ) {
096 rasterImageBlock = new RasterImageBlock [ rasterProductBlock.NumberOfRows ] ;
097 for ( int i= 0 ;i<rasterProductBlock.NumberOfRows;i++ ) {
098 rasterImageBlock [ i ] = new RasterImageBlock () ;
099 ok = ok && rasterImageBlock [ i ] .read ( fin ) ;
100 //rasterImageBlock[i].print();
101 }
102 }
103 return ( ok ) ;
104 }
105
106 /**
107 * 功能:绘制雷达背景图(图形区域为640*480,雷达图形区域为480*480,雷达站点信息区域为160*480)
108 * 参数:
109 * z - 缩放系数
110 * g - 图形设备
111 * c - 雷达中心位置
112 * pc - 极圈
113 * agl - 径线间隔,非正值则不画径线
114 * bnd - 省市县边界
115 * 返回值:
116 * 是否成功
117 */
118 public boolean drawBackground ( double z, Graphics2D g, Point c, boolean pc, double agl, boolean bnd ) {
119 if ( z <= 0.0 ) {
120 return ( false ) ;
121 }
122 try {
123 Polar polar = new Polar ( c, 0.001 *productDescriptionBlock.RadarLongitude, 0.001 *productDescriptionBlock.RadarLatitude ) ;
124 polar.setScale ( 1.0 *z ) ;
125 //以下两行改进线条的锯齿
126 RenderingHints renderHints = new RenderingHints ( RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON ) ;
127 g.setRenderingHints ( renderHints ) ;
128
129 // g.setColor(Color.black);//背景色
130 // g.fillRect(c.x-(int)(z*240), c.y-(int)(z*240), (int)(z*240*2), (int)(z*240*2));
131
132 g.setColor ( Color.white ) ; //雷达图形区域的边框颜色
133 g.drawRect ( c.x- ( int )( z* 240 ) , c.y- ( int )( z* 240 ) , ( int )( z* 240 * 2 ) , ( int )( z* 240 * 2 ) - 2 ) ;
134
135 if ( bnd ) { //画行政边界
136 Coordinate coordinate = new Coordinate ( polar ) ;
137 Diamond09.drawBorderline ( g, new Color ( 92 , 92 , 92 ) , coordinate, "/GIMDR/gmiss/config/CountyMap.dat" ) ;
138 Diamond09.drawBorderline ( g, new Color ( 160 , 160 , 160 ) , coordinate, "/GIMDR/gmiss/config/ProvinceMap.dat" ) ;
139 }
140
141 if ( pc ) { //画极圈
142 g.setColor ( new Color ( 255 , 255 , 255 )) ;
143 for ( int i= 50 ;i<= 200 ;i=i+ 50 ) { //每50公里画一个圈
144 g.drawArc ( c.x- ( int )( z*i ) , c.y- ( int )( z*i ) , ( int )( z*i ) * 2 , ( int )( z*i ) * 2 , 0 , 360 ) ;
145 }
146 g.drawArc ( c.x- ( int )( z* 240 ) , c.y- ( int )( z* 240 ) , ( int )( z* 240 ) * 2 , ( int )( z* 240 ) * 2 , 0 , 360 ) ; //外圈240公里
147 }
148
149 if ( agl >= 1.0 ) { //画极径
150 Point pos1, pos2;
151 for ( double i= 0.0 ;i< 180.0 ;i=i+agl ) {
152 pos1 = polar.getXY ( z* 240.0 , 0.0 +i ) ;
153 pos2 = polar.getXY ( z* 240.0 , 180.0 +i ) ;
154 g.drawLine ( pos1.x, pos1.y, pos2.x, pos2.y ) ;
155 }
156 }
157 return ( true ) ;
158 }
159 catch ( Exception ex ) {
160 System.out.println ( ex.getMessage ()) ;
161 ex.printStackTrace () ;
162 return ( false ) ;
163 }
164 }
165
166 /**
167 * 功能:绘制雷达信息区域
168 * 参数:
169 * g - 图形设备
170 * m - 雷达信息区域左上角位置
171 * 返回值:
172 * 是否成功
173 */
174 public boolean drawInformation ( Graphics2D g, Point m ) {
175 //以下两行改进线条的锯齿
176 RenderingHints renderHints = new RenderingHints ( RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON ) ;
177 g.setRenderingHints ( renderHints ) ;
178 g.setColor ( Color.white ) ; //信息区域的边框颜色
179 g.drawRect ( m.x, m.y, 160 , 479 ) ; //住处区域的边框
180 return ( true ) ;
181 }
182
183 /**
184 * 功能:绘制雷达产品图,根据不同类型分别调用相应的画图函数
185 * 参数:
186 * z - 缩放系数
187 * g - 图形设备
188 * c - 雷达中心位置
189 * 返回值:
190 * 是否成功
191 */
192 public boolean draw ( double z, Graphics2D g, Point c ) {
193 return (
194 z <= 0.0 ||
195 null == rasterProductBlock ||
196 rasterProductBlock.NumberOfRows <= 0 ||
197 drawRasterImage ( z, g, c )
198 ) ;
199 }
200
201 /**
202 * 功能:绘制RasterImage栅格图像(采用多边形填充法代替弧形填充)
203 * 参数:
204 * z - 缩放系数
205 * g - 图形设备
206 * c - 雷达中心位置
207 * 返回值:
208 * 是否成功
209 */
210 public boolean drawRasterImage ( double z, Graphics2D g, Point c ) {
211 Color [] colorRun = {
212 new Color ( 0 , 0 , 0 ) , new Color ( 156 , 156 , 156 ) , new Color ( 118 , 118 , 118 ) , new Color ( 250 , 170 , 170 ) ,
213 new Color ( 238 , 140 , 140 ) , new Color ( 200 , 112 , 112 ) , new Color ( 0 , 250 , 144 ) , new Color ( 0 , 186 , 0 ) ,
214 new Color ( 254 , 254 , 112 ) , new Color ( 208 , 208 , 96 ) , new Color ( 254 , 96 , 96 ) , new Color ( 218 , 0 , 0 ) ,
215 new Color ( 174 , 0 , 0 ) , new Color ( 0 , 0 , 254 ) , new Color ( 254 , 254 , 254 ) , new Color ( 230 , 0 , 254 )
216 } ;
217 // Polar polar = new Polar(c, 0.001*productDescriptionBlock.RadarLongitude, 0.001*productDescriptionBlock.RadarLatitude);
218 // polar.setScale(1.0);
219 //背景
220 //以下两行改进线条的锯齿
221 RenderingHints renderHints = new RenderingHints ( RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON ) ;
222 g.setRenderingHints ( renderHints ) ;
223
224 Point pos = new Point ( rasterProductBlock.CoordinateStartI, rasterProductBlock.CoordinateStartJ ) ;
225 Polygon p = new Polygon () ;
226 int iRun = - 1 ;
227 int iColor = - 1 ;
228 for ( int i= 0 ;i<rasterProductBlock.NumberOfRows;i++ ) {
229 pos.x = rasterProductBlock.CoordinateStartI + 8 ;
230 pos.y = rasterProductBlock.CoordinateStartJ + i * rasterProductBlock.ScaleY + 8 ;
231 for ( int j= 0 ;j<rasterImageBlock [ i ] .NumberOfBytesInRow;j++ ) {
232 iRun = rasterImageBlock [ i ] .Data [ j ] >> 4 & 0xF ;
233 iColor = rasterImageBlock [ i ] .Data [ j ] & 0xF ;
234 if ( iColor >= 0 && iColor < 16 ) {
235 g.setColor ( colorRun [ iColor ]) ;
236 g.fillRect ( pos.x, pos.y, ( int )( iRun*rasterProductBlock.ScaleX ) , rasterProductBlock.ScaleY ) ;
237 g.drawRect ( pos.x, pos.y, ( int )( iRun*rasterProductBlock.ScaleX ) , rasterProductBlock.ScaleY ) ;
238 }
239 pos.x = pos.x + iRun*rasterProductBlock.ScaleX;
240 }
241 }
242 return ( true ) ;
243 }
244 }
RasterImageBlock.java
001 /**
002 * PACKAGE : cma.gmb.doppler.datatype
003 FILENAME : RasterImageBlock.java
004 * DESCRIPTION : 多普勒雷达产品数据结构(Raster格式)
005 * AUTHOR : 刘泽军
006 * EMAIL : BJ0773@gmail.com
007 * Date : 2007-06-07 16:24:11
008 * Update :
009 * Reference : 《NEXRAD LEVEL II数据格式》中文版及英文版
010 */
011
012 package cma.gmb.doppler.datatype;
013
014 import java.io.*;
015 import java.lang.*;
016
017 import cma.common.dataio.*;
018
019 public class RasterImageBlock { //极坐标栅格图像数据
020
021 public static int SIZE = 2 ;
022
023 public short NumberOfBytesInRow;
024 public byte [] Data;
025
026 /**
027 * 功能:构造函数
028 * 参数:
029 * 无
030 * 返回:
031 * 无
032 */
033 public RasterImageBlock () {
034 }
035
036 /**
037 * 功能:从随机文件中读取数据,并进行BigEndian转换
038 * 参数:
039 * raf - 随机访问的文件对象
040 * 返回:
041 * 是否成功
042 */
043 public boolean read ( RandomAccessFile raf ) {
044 try {
045 byte [] buf = new byte [ RasterImageBlock.SIZE ] ;
046 int len = raf.read ( buf ) ;
047 boolean ok = len == RasterImageBlock.SIZE ? parse ( buf, 0 ) : false ;
048 if ( ok && NumberOfBytesInRow > 0 ) {
049 Data = new byte [ NumberOfBytesInRow ] ;
050 len = raf.read ( Data ) ;
051 }
052 return ( ok && len == NumberOfBytesInRow ) ;
053 }
054 catch ( Exception ex ) {
055 return ( false ) ;
056 }
057 }
058
059 /**
060 * 功能:从输入流文件中读取数据,并进行BigEndian转换
061 * (主要是为了从 .tar.gz 中读取)
062 * 参数:
063 * in - InputStream对象
064 * 返回:
065 * 是否成功
066 */
067 public boolean read ( InputStream in ) {
068 try {
069 byte [] buf = new byte [ RasterImageBlock.SIZE ] ;
070 int len = in.read ( buf ) ;
071 boolean ok = len == RasterImageBlock.SIZE ? parse ( buf, 0 ) : false ;
072 if ( ok && NumberOfBytesInRow > 0 ) {
073 Data = new byte [ NumberOfBytesInRow ] ;
074 len = in.read ( Data ) ;
075 }
076 return ( ok && len == NumberOfBytesInRow ) ;
077 }
078 catch ( Exception ex ) {
079 return ( false ) ;
080 }
081 }
082
083 /**
084 * 功能:从缓冲区中读取数据,并进行BigEndian转换
085 * 参数:
086 * in - InputStream对象
087 * 返回:
088 * 是否成功
089 */
090 public int read ( byte [] buf, int index ) {
091 boolean ok = parse ( buf, index ) ;
092 if ( ok && NumberOfBytesInRow > 0 && buf.length >= index+NumberOfBytesInRow ) {
093 Data = new byte [ NumberOfBytesInRow ] ;
094 for ( int i= 0 ;i<NumberOfBytesInRow;i++ ) {
095 Data [ i ] = buf [ index+i ] ;
096 }
097 return ( RasterImageBlock.SIZE+NumberOfBytesInRow ) ;
098 }
099 return ( 0 ) ;
100 }
101
102 /**
103 * 功能:从缓冲区中分析出数据
104 * 参数:
105 * buf - 缓冲数据
106 * 返回:
107 * 是否成功
108 */
109 public boolean parse ( byte [] buf ) {
110 return ( parse ( buf, 0 )) ;
111 }
112
113 /**
114 * 功能:从缓冲区中分析出数据
115 * 参数:
116 * buf - 缓冲数据
117 * index - 偏移
118 * 返回:
119 * 是否成功
120 */
121 public boolean parse ( byte [] buf, int index ) {
122 NumberOfBytesInRow = DataConverterBE.getShort ( buf, index+ 0 ) ;
123 return ( true ) ;
124 }
125
126 /**
127 * 功能:获得数据信息
128 * 参数:
129 * 无
130 * 返回:
131 * 数据信息
132 */
133 public String info () {
134 String msg =
135 "/nRasterImageBlock.SIZE = " + String.valueOf ( RasterImageBlock.SIZE ) +
136 "/n NumberOfBytesInRow = " + String.valueOf ( NumberOfBytesInRow ) +
137 "/n" ;
138 /* for(int i=0;i<NumberOfRadialRLE*2;i++) {
139 msg = msg + String.valueOf((new Byte(Data[i])).intValue()/16)+","+String.valueOf((new Byte(Data[i])).intValue()%16)+" ";
140 }
141 msg = msg + "/n";
142 */
143 return ( msg ) ;
144 }
145 /**
146 * 功能:打印数据,主要用于测试
147 * 参数:
148 * 无
149 * 返回:
150 * 无
151 */
152 public void print () {
153 System.out.println ( info ()) ;
154 }
155
156 }
RasterProductBlock.java
001 /**
002 * PACKAGE : cma.gmb.doppler.datatype
003 FILENAME : RasterProductBlock.java
004 * DESCRIPTION : 多普勒雷达产品数据结构(Raster格式)
005 * AUTHOR : 刘泽军
006 * EMAIL : BJ0773@gmail.com
007 * Date : 2007-06-07 17:09:47
008 * Update :
009 * Reference : 《NEXRAD LEVEL II数据格式》中文版及英文版
010 */
011
012 package cma.gmb.doppler.datatype;
013
014 import java.io.*;
015 import java.lang.*;
016
017 import cma.common.dataio.*;
018
019 public class RasterProductBlock { //层数据包
020
021 public static int SIZE = 20 ;
022
023 public String PacketCode1;
024 public String PacketCode2;
025 public short CoordinateStartI;
026 public short CoordinateStartJ;
027 public short ScaleX;
028 public short ScaleFractionalX;
029 public short ScaleY;
030 public short ScaleFractionalY;
031 public short NumberOfRows;
032 public short PackingDescriptor;
033
034 /**
035 * 功能:构造函数
036 * 参数:
037 * 无
038 * 返回:
039 * 无
040 */
041 public RasterProductBlock () {
042 }
043
044 /**
045 * 功能:从文件中读取数据,并进行BigEndian转换
046 * 参数:
047 * raf - 随机访问的文件对象
048 * 返回:
049 * 是否成功
050 */
051 public boolean read ( RandomAccessFile raf ) {
052 try {
053 byte [] buf = new byte [ RasterProductBlock.SIZE ] ;
054 int len = raf.read ( buf ) ;
055 return ( len == RasterProductBlock.SIZE ? parse ( buf, 0 ) : false ) ;
056 }
057 catch ( Exception ex ) {
058 return ( false ) ;
059 }
060 }
061
062 /**
063 * 功能:从输入流文件中读取数据,并进行BigEndian转换
064 * 参数:
065 * in - InputStream对象
066 * 返回:
067 * 是否成功
068 */
069 public boolean read ( InputStream in ) {
070 try {
071 byte [] buf = new byte [ RasterProductBlock.SIZE ] ;
072 int len = in.read ( buf ) ;
073 return ( len == RasterProductBlock.SIZE ? parse ( buf, 0 ) : false ) ;
074 }
075 catch ( Exception ex ) {
076 return ( false ) ;
077 }
078 }
079
080 /**
081 * 功能:从缓冲区中读数据
082 * (在外部方法中,一次性读入所有数据,然后逐类分析数据)
083 * 参数:
084 * buf - 缓冲数据
085 * index - 偏移
086 * 返回:
087 * 正确读出的数据字节数
088 */
089 public int read ( byte [] buf, int index ) {
090 return ( parse ( buf, index ) ?RasterProductBlock.SIZE: 0 ) ;
091 }
092
093 /**
094 * 功能:从缓冲区中分析出数据
095 * 参数:
096 * buf - 缓冲数据
097 * 返回:
098 * 是否成功
099 */
100 public boolean parse ( byte [] buf ) {
101 return ( parse ( buf, 0 )) ;
102 }
103
104 /**
105 * 功能:从缓冲区中分析出数据
106 * 参数:
107 * buf - 缓冲数据
108 * index - 偏移
109 * 返回:
110 * 是否成功
111 */
112 public boolean parse ( byte [] buf, int index ) {
113 PacketCode1 = DataConverterBE.getHex ( buf, index+ 0 , 2 ) ;
114 PacketCode2 = DataConverterBE.getHex ( buf, index+ 2 , 2 ) ;
115 CoordinateStartI = DataConverterBE.getShort ( buf, index+ 4 ) ;
116 CoordinateStartJ = DataConverterBE.getShort ( buf, index+ 6 ) ;
117 ScaleX = DataConverterBE.getShort ( buf, index+ 8 ) ;
118 ScaleFractionalX = DataConverterBE.getShort ( buf, index+ 10 ) ;
119 ScaleY = DataConverterBE.getShort ( buf, index+ 12 ) ;
120 ScaleFractionalY = DataConverterBE.getShort ( buf, index+ 14 ) ;
121 NumberOfRows = DataConverterBE.getShort ( buf, index+ 16 ) ;
122 PackingDescriptor = DataConverterBE.getShort ( buf, index+ 18 ) ;
123 return ( true ) ;
124 }
125
126 /**
127 * 功能:获得数据信息
128 * 参数:
129 * 无
130 * 返回:
131 * 数据信息
132 */
133 public String info () {
134 String msg =
135 "/nRasterProductBlock.SIZE = " + String.valueOf ( RasterProductBlock.SIZE ) +
136 "/n PacketCode1 = " + String.valueOf ( PacketCode1 ) +
137 "/n PacketCode2 = " + String.valueOf ( PacketCode2 ) +
138 "/n CoordinateStartI = " + String.valueOf ( CoordinateStartI ) +
139 "/n CoordinateStartJ = " + String.valueOf ( CoordinateStartJ ) +
140 "/n ScaleX = " + String.valueOf ( ScaleX ) +
141 "/n ScaleFractionalX = " + String.valueOf ( ScaleFractionalX ) +
142 "/n ScaleY = " + String.valueOf ( ScaleY ) +
143 "/n ScaleFractionalY = " + String.valueOf ( ScaleFractionalY ) +
144 "/n NumberOfRows = " + String.valueOf ( NumberOfRows ) +
145 "/n PackingDescriptor = " + String.valueOf ( PackingDescriptor ) +
146 "/n" ;
147 return ( msg ) ;
148 }
149
150 /**
151 * 功能:打印数据,主要用于测试
152 * 参数:
153 * 无
154 * 返回:
155 * 无
156 */
157 public void print () {
158 System.out.println ( info ()) ;
159 }
160
161 }
包含RasterImage.java、RasterImageBlock.java、RasterProductBlock.java三个类。
由SymbologyImage.java类判断产品为Symbology且特征码为BA0F或BA07时调用。
RasterImage.java
001 /**
002 * PACKAGE : cma.gmb.doppler
003 * FILENAME : RasterImage.java
004 * DESCRIPTION : 处理多普勒雷达产品数据(格栅产品Raster)
005 * AUTHOR : 刘泽军
006 * EMAIL : BJ0773@gmail.com
007 * Date : 2007-06-02 23:52:38
008 * Update : 2007-06-13 从SymbologyImage.java中独立出来
009 * Reference : 《National Climatic Data Center DATA DOCUMENTATION FOR TD7000 -
010 * TD7599 NEXRAD LEVEL III》
011 *
012 */
013
014 package cma.gmb.doppler;
015
016 import java.io.*;
017 import java.awt.*;
018
019 import cma.common.dataio.*;
020 import cma.common.projection.*;
021 import cma.micaps.diamond.*;
022 import cma.gmb.doppler.datatype.*;
023
024 public class RasterImage {
025 //外部传入的数据
026 public MessageHeaderBlock messageHeaderBlock;
027 public ProductDescriptionBlock productDescriptionBlock;
028 public ProductSymbologyBlock productSymbologyBlock;
029 public ProductSymbologyLayerBlock productSymbologyLayerBlock;
030 //需要读取的数据
031 public RasterProductBlock rasterProductBlock;
032 public RasterImageBlock [] rasterImageBlock;
033
034 public static Color [] levels = {
035 new Color ( 0 , 0 , 0 ) , new Color ( 0 , 0 , 246 ) , new Color ( 1 , 159 , 246 ) , new Color ( 0 , 236 , 236 ) ,
036 new Color ( 1 , 255 , 0 ) , new Color ( 0 , 200 , 0 ) , new Color ( 1 , 144 , 0 ) , new Color ( 255 , 255 , 0 ) ,
037 new Color ( 231 , 192 , 0 ) , new Color ( 255 , 144 , 0 ) , new Color ( 254 , 0 , 0 ) , new Color ( 214 , 0 , 0 ) ,
038 new Color ( 192 , 0 , 0 ) , new Color ( 255 , 0 , 250 ) , new Color ( 174 , 144 , 240 ) , new Color ( 255 , 255 , 255 )
039 } ;
040
041 /**
042 * 功能:构造函数
043 * 参数:
044 * 无
045 * 返回值:
046 * 无
047 */
048 public RasterImage () {
049 }
050
051 /**
052 * 功能:读取多普勒栅格数据Raster Image,不包括文件头信息,注意在调用前先定位好偏移量
053 * 参数:
054 * fin - 随机访问的文件对象
055 * 返回值:
056 * 是否成功
057 */
058 public boolean read ( RandomAccessFile fin ) throws Exception {
059
060 if ( ! "BA0F" .equalsIgnoreCase ( productSymbologyLayerBlock.PacketCode ) &&
061 ! "BA07" .equalsIgnoreCase ( productSymbologyLayerBlock.PacketCode ) ) { //非栅格数据 Raster Image
062 return ( false ) ;
063 }
064 boolean ok = false ;
065 rasterProductBlock = new RasterProductBlock () ;
066 ok = rasterProductBlock.read ( fin ) ;
067 if ( rasterProductBlock.NumberOfRows > 0 ) {
068 rasterImageBlock = new RasterImageBlock [ rasterProductBlock.NumberOfRows ] ;
069 for ( int i= 0 ;i<rasterProductBlock.NumberOfRows;i++ ) {
070 rasterImageBlock [ i ] = new RasterImageBlock () ;
071 ok = ok && rasterImageBlock [ i ] .read ( fin ) ;
072 }
073 }
074 return ( ok ) ;
075 }
076
077 /**
078 * 2007-06-04增加,并在相关的类中增加 read(InputStream fin) 方法
079 *
080 * 功能:从数据流中读取多普勒栅格数据Raster,主要是考虑直接从 .tar.gz 中读取
081 * 参数:
082 * fin - InputStream,注意不能使用 fin.close() 方法,因为在函数外部可能还需要继续从 fin 读数据
083 * 返回值:
084 * 是否成功
085 */
086 public boolean read ( InputStream fin ) throws Exception {
087
088 if ( ! "BA0F" .equalsIgnoreCase ( productSymbologyLayerBlock.PacketCode ) &&
089 ! "BA07" .equalsIgnoreCase ( productSymbologyLayerBlock.PacketCode ) ) { //非栅格数据 Raster Image
090 return ( false ) ;
091 }
092 boolean ok = false ;
093 rasterProductBlock = new RasterProductBlock () ;
094 ok = rasterProductBlock.read ( fin ) ;
095 if ( rasterProductBlock.NumberOfRows > 0 ) {
096 rasterImageBlock = new RasterImageBlock [ rasterProductBlock.NumberOfRows ] ;
097 for ( int i= 0 ;i<rasterProductBlock.NumberOfRows;i++ ) {
098 rasterImageBlock [ i ] = new RasterImageBlock () ;
099 ok = ok && rasterImageBlock [ i ] .read ( fin ) ;
100 //rasterImageBlock[i].print();
101 }
102 }
103 return ( ok ) ;
104 }
105
106 /**
107 * 功能:绘制雷达背景图(图形区域为640*480,雷达图形区域为480*480,雷达站点信息区域为160*480)
108 * 参数:
109 * z - 缩放系数
110 * g - 图形设备
111 * c - 雷达中心位置
112 * pc - 极圈
113 * agl - 径线间隔,非正值则不画径线
114 * bnd - 省市县边界
115 * 返回值:
116 * 是否成功
117 */
118 public boolean drawBackground ( double z, Graphics2D g, Point c, boolean pc, double agl, boolean bnd ) {
119 if ( z <= 0.0 ) {
120 return ( false ) ;
121 }
122 try {
123 Polar polar = new Polar ( c, 0.001 *productDescriptionBlock.RadarLongitude, 0.001 *productDescriptionBlock.RadarLatitude ) ;
124 polar.setScale ( 1.0 *z ) ;
125 //以下两行改进线条的锯齿
126 RenderingHints renderHints = new RenderingHints ( RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON ) ;
127 g.setRenderingHints ( renderHints ) ;
128
129 // g.setColor(Color.black);//背景色
130 // g.fillRect(c.x-(int)(z*240), c.y-(int)(z*240), (int)(z*240*2), (int)(z*240*2));
131
132 g.setColor ( Color.white ) ; //雷达图形区域的边框颜色
133 g.drawRect ( c.x- ( int )( z* 240 ) , c.y- ( int )( z* 240 ) , ( int )( z* 240 * 2 ) , ( int )( z* 240 * 2 ) - 2 ) ;
134
135 if ( bnd ) { //画行政边界
136 Coordinate coordinate = new Coordinate ( polar ) ;
137 Diamond09.drawBorderline ( g, new Color ( 92 , 92 , 92 ) , coordinate, "/GIMDR/gmiss/config/CountyMap.dat" ) ;
138 Diamond09.drawBorderline ( g, new Color ( 160 , 160 , 160 ) , coordinate, "/GIMDR/gmiss/config/ProvinceMap.dat" ) ;
139 }
140
141 if ( pc ) { //画极圈
142 g.setColor ( new Color ( 255 , 255 , 255 )) ;
143 for ( int i= 50 ;i<= 200 ;i=i+ 50 ) { //每50公里画一个圈
144 g.drawArc ( c.x- ( int )( z*i ) , c.y- ( int )( z*i ) , ( int )( z*i ) * 2 , ( int )( z*i ) * 2 , 0 , 360 ) ;
145 }
146 g.drawArc ( c.x- ( int )( z* 240 ) , c.y- ( int )( z* 240 ) , ( int )( z* 240 ) * 2 , ( int )( z* 240 ) * 2 , 0 , 360 ) ; //外圈240公里
147 }
148
149 if ( agl >= 1.0 ) { //画极径
150 Point pos1, pos2;
151 for ( double i= 0.0 ;i< 180.0 ;i=i+agl ) {
152 pos1 = polar.getXY ( z* 240.0 , 0.0 +i ) ;
153 pos2 = polar.getXY ( z* 240.0 , 180.0 +i ) ;
154 g.drawLine ( pos1.x, pos1.y, pos2.x, pos2.y ) ;
155 }
156 }
157 return ( true ) ;
158 }
159 catch ( Exception ex ) {
160 System.out.println ( ex.getMessage ()) ;
161 ex.printStackTrace () ;
162 return ( false ) ;
163 }
164 }
165
166 /**
167 * 功能:绘制雷达信息区域
168 * 参数:
169 * g - 图形设备
170 * m - 雷达信息区域左上角位置
171 * 返回值:
172 * 是否成功
173 */
174 public boolean drawInformation ( Graphics2D g, Point m ) {
175 //以下两行改进线条的锯齿
176 RenderingHints renderHints = new RenderingHints ( RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON ) ;
177 g.setRenderingHints ( renderHints ) ;
178 g.setColor ( Color.white ) ; //信息区域的边框颜色
179 g.drawRect ( m.x, m.y, 160 , 479 ) ; //住处区域的边框
180 return ( true ) ;
181 }
182
183 /**
184 * 功能:绘制雷达产品图,根据不同类型分别调用相应的画图函数
185 * 参数:
186 * z - 缩放系数
187 * g - 图形设备
188 * c - 雷达中心位置
189 * 返回值:
190 * 是否成功
191 */
192 public boolean draw ( double z, Graphics2D g, Point c ) {
193 return (
194 z <= 0.0 ||
195 null == rasterProductBlock ||
196 rasterProductBlock.NumberOfRows <= 0 ||
197 drawRasterImage ( z, g, c )
198 ) ;
199 }
200
201 /**
202 * 功能:绘制RasterImage栅格图像(采用多边形填充法代替弧形填充)
203 * 参数:
204 * z - 缩放系数
205 * g - 图形设备
206 * c - 雷达中心位置
207 * 返回值:
208 * 是否成功
209 */
210 public boolean drawRasterImage ( double z, Graphics2D g, Point c ) {
211 Color [] colorRun = {
212 new Color ( 0 , 0 , 0 ) , new Color ( 156 , 156 , 156 ) , new Color ( 118 , 118 , 118 ) , new Color ( 250 , 170 , 170 ) ,
213 new Color ( 238 , 140 , 140 ) , new Color ( 200 , 112 , 112 ) , new Color ( 0 , 250 , 144 ) , new Color ( 0 , 186 , 0 ) ,
214 new Color ( 254 , 254 , 112 ) , new Color ( 208 , 208 , 96 ) , new Color ( 254 , 96 , 96 ) , new Color ( 218 , 0 , 0 ) ,
215 new Color ( 174 , 0 , 0 ) , new Color ( 0 , 0 , 254 ) , new Color ( 254 , 254 , 254 ) , new Color ( 230 , 0 , 254 )
216 } ;
217 // Polar polar = new Polar(c, 0.001*productDescriptionBlock.RadarLongitude, 0.001*productDescriptionBlock.RadarLatitude);
218 // polar.setScale(1.0);
219 //背景
220 //以下两行改进线条的锯齿
221 RenderingHints renderHints = new RenderingHints ( RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON ) ;
222 g.setRenderingHints ( renderHints ) ;
223
224 Point pos = new Point ( rasterProductBlock.CoordinateStartI, rasterProductBlock.CoordinateStartJ ) ;
225 Polygon p = new Polygon () ;
226 int iRun = - 1 ;
227 int iColor = - 1 ;
228 for ( int i= 0 ;i<rasterProductBlock.NumberOfRows;i++ ) {
229 pos.x = rasterProductBlock.CoordinateStartI + 8 ;
230 pos.y = rasterProductBlock.CoordinateStartJ + i * rasterProductBlock.ScaleY + 8 ;
231 for ( int j= 0 ;j<rasterImageBlock [ i ] .NumberOfBytesInRow;j++ ) {
232 iRun = rasterImageBlock [ i ] .Data [ j ] >> 4 & 0xF ;
233 iColor = rasterImageBlock [ i ] .Data [ j ] & 0xF ;
234 if ( iColor >= 0 && iColor < 16 ) {
235 g.setColor ( colorRun [ iColor ]) ;
236 g.fillRect ( pos.x, pos.y, ( int )( iRun*rasterProductBlock.ScaleX ) , rasterProductBlock.ScaleY ) ;
237 g.drawRect ( pos.x, pos.y, ( int )( iRun*rasterProductBlock.ScaleX ) , rasterProductBlock.ScaleY ) ;
238 }
239 pos.x = pos.x + iRun*rasterProductBlock.ScaleX;
240 }
241 }
242 return ( true ) ;
243 }
244 }
RasterImageBlock.java
001 /**
002 * PACKAGE : cma.gmb.doppler.datatype
003 FILENAME : RasterImageBlock.java
004 * DESCRIPTION : 多普勒雷达产品数据结构(Raster格式)
005 * AUTHOR : 刘泽军
006 * EMAIL : BJ0773@gmail.com
007 * Date : 2007-06-07 16:24:11
008 * Update :
009 * Reference : 《NEXRAD LEVEL II数据格式》中文版及英文版
010 */
011
012 package cma.gmb.doppler.datatype;
013
014 import java.io.*;
015 import java.lang.*;
016
017 import cma.common.dataio.*;
018
019 public class RasterImageBlock { //极坐标栅格图像数据
020
021 public static int SIZE = 2 ;
022
023 public short NumberOfBytesInRow;
024 public byte [] Data;
025
026 /**
027 * 功能:构造函数
028 * 参数:
029 * 无
030 * 返回:
031 * 无
032 */
033 public RasterImageBlock () {
034 }
035
036 /**
037 * 功能:从随机文件中读取数据,并进行BigEndian转换
038 * 参数:
039 * raf - 随机访问的文件对象
040 * 返回:
041 * 是否成功
042 */
043 public boolean read ( RandomAccessFile raf ) {
044 try {
045 byte [] buf = new byte [ RasterImageBlock.SIZE ] ;
046 int len = raf.read ( buf ) ;
047 boolean ok = len == RasterImageBlock.SIZE ? parse ( buf, 0 ) : false ;
048 if ( ok && NumberOfBytesInRow > 0 ) {
049 Data = new byte [ NumberOfBytesInRow ] ;
050 len = raf.read ( Data ) ;
051 }
052 return ( ok && len == NumberOfBytesInRow ) ;
053 }
054 catch ( Exception ex ) {
055 return ( false ) ;
056 }
057 }
058
059 /**
060 * 功能:从输入流文件中读取数据,并进行BigEndian转换
061 * (主要是为了从 .tar.gz 中读取)
062 * 参数:
063 * in - InputStream对象
064 * 返回:
065 * 是否成功
066 */
067 public boolean read ( InputStream in ) {
068 try {
069 byte [] buf = new byte [ RasterImageBlock.SIZE ] ;
070 int len = in.read ( buf ) ;
071 boolean ok = len == RasterImageBlock.SIZE ? parse ( buf, 0 ) : false ;
072 if ( ok && NumberOfBytesInRow > 0 ) {
073 Data = new byte [ NumberOfBytesInRow ] ;
074 len = in.read ( Data ) ;
075 }
076 return ( ok && len == NumberOfBytesInRow ) ;
077 }
078 catch ( Exception ex ) {
079 return ( false ) ;
080 }
081 }
082
083 /**
084 * 功能:从缓冲区中读取数据,并进行BigEndian转换
085 * 参数:
086 * in - InputStream对象
087 * 返回:
088 * 是否成功
089 */
090 public int read ( byte [] buf, int index ) {
091 boolean ok = parse ( buf, index ) ;
092 if ( ok && NumberOfBytesInRow > 0 && buf.length >= index+NumberOfBytesInRow ) {
093 Data = new byte [ NumberOfBytesInRow ] ;
094 for ( int i= 0 ;i<NumberOfBytesInRow;i++ ) {
095 Data [ i ] = buf [ index+i ] ;
096 }
097 return ( RasterImageBlock.SIZE+NumberOfBytesInRow ) ;
098 }
099 return ( 0 ) ;
100 }
101
102 /**
103 * 功能:从缓冲区中分析出数据
104 * 参数:
105 * buf - 缓冲数据
106 * 返回:
107 * 是否成功
108 */
109 public boolean parse ( byte [] buf ) {
110 return ( parse ( buf, 0 )) ;
111 }
112
113 /**
114 * 功能:从缓冲区中分析出数据
115 * 参数:
116 * buf - 缓冲数据
117 * index - 偏移
118 * 返回:
119 * 是否成功
120 */
121 public boolean parse ( byte [] buf, int index ) {
122 NumberOfBytesInRow = DataConverterBE.getShort ( buf, index+ 0 ) ;
123 return ( true ) ;
124 }
125
126 /**
127 * 功能:获得数据信息
128 * 参数:
129 * 无
130 * 返回:
131 * 数据信息
132 */
133 public String info () {
134 String msg =
135 "/nRasterImageBlock.SIZE = " + String.valueOf ( RasterImageBlock.SIZE ) +
136 "/n NumberOfBytesInRow = " + String.valueOf ( NumberOfBytesInRow ) +
137 "/n" ;
138 /* for(int i=0;i<NumberOfRadialRLE*2;i++) {
139 msg = msg + String.valueOf((new Byte(Data[i])).intValue()/16)+","+String.valueOf((new Byte(Data[i])).intValue()%16)+" ";
140 }
141 msg = msg + "/n";
142 */
143 return ( msg ) ;
144 }
145 /**
146 * 功能:打印数据,主要用于测试
147 * 参数:
148 * 无
149 * 返回:
150 * 无
151 */
152 public void print () {
153 System.out.println ( info ()) ;
154 }
155
156 }
RasterProductBlock.java
001 /**
002 * PACKAGE : cma.gmb.doppler.datatype
003 FILENAME : RasterProductBlock.java
004 * DESCRIPTION : 多普勒雷达产品数据结构(Raster格式)
005 * AUTHOR : 刘泽军
006 * EMAIL : BJ0773@gmail.com
007 * Date : 2007-06-07 17:09:47
008 * Update :
009 * Reference : 《NEXRAD LEVEL II数据格式》中文版及英文版
010 */
011
012 package cma.gmb.doppler.datatype;
013
014 import java.io.*;
015 import java.lang.*;
016
017 import cma.common.dataio.*;
018
019 public class RasterProductBlock { //层数据包
020
021 public static int SIZE = 20 ;
022
023 public String PacketCode1;
024 public String PacketCode2;
025 public short CoordinateStartI;
026 public short CoordinateStartJ;
027 public short ScaleX;
028 public short ScaleFractionalX;
029 public short ScaleY;
030 public short ScaleFractionalY;
031 public short NumberOfRows;
032 public short PackingDescriptor;
033
034 /**
035 * 功能:构造函数
036 * 参数:
037 * 无
038 * 返回:
039 * 无
040 */
041 public RasterProductBlock () {
042 }
043
044 /**
045 * 功能:从文件中读取数据,并进行BigEndian转换
046 * 参数:
047 * raf - 随机访问的文件对象
048 * 返回:
049 * 是否成功
050 */
051 public boolean read ( RandomAccessFile raf ) {
052 try {
053 byte [] buf = new byte [ RasterProductBlock.SIZE ] ;
054 int len = raf.read ( buf ) ;
055 return ( len == RasterProductBlock.SIZE ? parse ( buf, 0 ) : false ) ;
056 }
057 catch ( Exception ex ) {
058 return ( false ) ;
059 }
060 }
061
062 /**
063 * 功能:从输入流文件中读取数据,并进行BigEndian转换
064 * 参数:
065 * in - InputStream对象
066 * 返回:
067 * 是否成功
068 */
069 public boolean read ( InputStream in ) {
070 try {
071 byte [] buf = new byte [ RasterProductBlock.SIZE ] ;
072 int len = in.read ( buf ) ;
073 return ( len == RasterProductBlock.SIZE ? parse ( buf, 0 ) : false ) ;
074 }
075 catch ( Exception ex ) {
076 return ( false ) ;
077 }
078 }
079
080 /**
081 * 功能:从缓冲区中读数据
082 * (在外部方法中,一次性读入所有数据,然后逐类分析数据)
083 * 参数:
084 * buf - 缓冲数据
085 * index - 偏移
086 * 返回:
087 * 正确读出的数据字节数
088 */
089 public int read ( byte [] buf, int index ) {
090 return ( parse ( buf, index ) ?RasterProductBlock.SIZE: 0 ) ;
091 }
092
093 /**
094 * 功能:从缓冲区中分析出数据
095 * 参数:
096 * buf - 缓冲数据
097 * 返回:
098 * 是否成功
099 */
100 public boolean parse ( byte [] buf ) {
101 return ( parse ( buf, 0 )) ;
102 }
103
104 /**
105 * 功能:从缓冲区中分析出数据
106 * 参数:
107 * buf - 缓冲数据
108 * index - 偏移
109 * 返回:
110 * 是否成功
111 */
112 public boolean parse ( byte [] buf, int index ) {
113 PacketCode1 = DataConverterBE.getHex ( buf, index+ 0 , 2 ) ;
114 PacketCode2 = DataConverterBE.getHex ( buf, index+ 2 , 2 ) ;
115 CoordinateStartI = DataConverterBE.getShort ( buf, index+ 4 ) ;
116 CoordinateStartJ = DataConverterBE.getShort ( buf, index+ 6 ) ;
117 ScaleX = DataConverterBE.getShort ( buf, index+ 8 ) ;
118 ScaleFractionalX = DataConverterBE.getShort ( buf, index+ 10 ) ;
119 ScaleY = DataConverterBE.getShort ( buf, index+ 12 ) ;
120 ScaleFractionalY = DataConverterBE.getShort ( buf, index+ 14 ) ;
121 NumberOfRows = DataConverterBE.getShort ( buf, index+ 16 ) ;
122 PackingDescriptor = DataConverterBE.getShort ( buf, index+ 18 ) ;
123 return ( true ) ;
124 }
125
126 /**
127 * 功能:获得数据信息
128 * 参数:
129 * 无
130 * 返回:
131 * 数据信息
132 */
133 public String info () {
134 String msg =
135 "/nRasterProductBlock.SIZE = " + String.valueOf ( RasterProductBlock.SIZE ) +
136 "/n PacketCode1 = " + String.valueOf ( PacketCode1 ) +
137 "/n PacketCode2 = " + String.valueOf ( PacketCode2 ) +
138 "/n CoordinateStartI = " + String.valueOf ( CoordinateStartI ) +
139 "/n CoordinateStartJ = " + String.valueOf ( CoordinateStartJ ) +
140 "/n ScaleX = " + String.valueOf ( ScaleX ) +
141 "/n ScaleFractionalX = " + String.valueOf ( ScaleFractionalX ) +
142 "/n ScaleY = " + String.valueOf ( ScaleY ) +
143 "/n ScaleFractionalY = " + String.valueOf ( ScaleFractionalY ) +
144 "/n NumberOfRows = " + String.valueOf ( NumberOfRows ) +
145 "/n PackingDescriptor = " + String.valueOf ( PackingDescriptor ) +
146 "/n" ;
147 return ( msg ) ;
148 }
149
150 /**
151 * 功能:打印数据,主要用于测试
152 * 参数:
153 * 无
154 * 返回:
155 * 无
156 */
157 public void print () {
158 System.out.println ( info ()) ;
159 }
160
161 }