多普勒天气雷达的体扫产品处理代码。
包含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 }