Doppler天气雷达扫描产品(RadialImage)

本文介绍了一种用于处理多普勒天气雷达体扫产品的Java代码实现,包括RadialImage、RadialImageBlock和RadialProductBlock三个核心类,支持从文件中读取雷达数据并绘制雷达图像。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多普勒天气雷达的体扫产品处理代码。
包含RadialImage.java、RadialImageBlock.java、RadialProductBlock.java三个类。
由SymbologyImage.java类判断产品为Symbology且特征码为AF1F时调用。

 


RadialImage.java
001 /**
002  * PACKAGE      : cma.gmb.doppler
003  * FILENAME     : RadialImage.java
004  * DESCRIPTION  : 处理多普勒雷达产品数据(扫描产品Radial)
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  * 注:部份代码参考了山东装备中心黄磊(stonehuang@126.com)的Pascal代码,特此声明并致谢。
013  *
014  */
015 
016 package cma.gmb.doppler;
017 
018 import java.io.*;
019 import java.awt.*;
020 
021 import cma.common.dataio.*;
022 import cma.common.projection.*;
023 import cma.micaps.diamond.*;
024 import cma.gmb.doppler.datatype.*;
025 
026 public class RadialImage {
027 
028     //外部传入的数据
029     public  MessageHeaderBlock          messageHeaderBlock;
030     public  ProductDescriptionBlock     productDescriptionBlock;
031     public  ProductSymbologyBlock       productSymbologyBlock;
032     public  ProductSymbologyLayerBlock  productSymbologyLayerBlock;
033 
034     //需要读取的数据
035     public  RadialProductBlock          radialProductBlock;
036     public  RadialImageBlock[]          radialImageBlock;
037 
038     public  static  Color[] levels  = {
039         new Color(  0,  0,  0)new Color(  0,  0,246)new Color(  1,159,246)new Color(  0,236,236),
040         new Color(  1,255,  0)new Color(  0,200,  0)new Color(  1,144,  0)new Color(255,255,  0),
041         new Color(231,192,  0)new Color(255,144,  0)new Color(254,  0,  0)new Color(214,  0,  0),
042         new Color(192,  0,  0)new Color(255,  0,250)new Color(174,144,240)new Color(255,255,255)
043     };
044 
045 /**
046  * 功能:构造函数
047  * 参数:
048  *      无
049  * 返回值:
050  *      无
051  */
052     public RadialImage() {
053     }
054 
055 /**
056  * 功能:读取Radial Image产品数据,不包括文件头信息,注意在调用前先定位好偏移量
057  * 参数:
058  *      fin     - 随机访问文件
059  * 返回值:
060  *      是否成功
061  */
062     public boolean read(RandomAccessFile finthrows Exception {
063 
064         if!"AF1F".equalsIgnoreCase(productSymbologyLayerBlock.PacketCode) ) {//非扫描数据 Radial Image
065             return(false);
066         }
067         boolean ok  = false;
068         radialProductBlock      = new RadialProductBlock();
069         ok  = radialProductBlock.read(fin);
070         ifok && radialProductBlock.NumberOfRadials > ) {
071             radialImageBlock    = new RadialImageBlock[radialProductBlock.NumberOfRadials];
072             for(int i=0;i<radialProductBlock.NumberOfRadials;i++) {
073                 radialImageBlock[inew RadialImageBlock();
074                 ok  = ok && radialImageBlock[i].read(fin);
075             }
076         }
077         return(ok);
078     }
079 
080 /**
081  * 功能:读取Radial Image产品数据,不包括文件头信息,注意在调用前先定位好读取偏移。主要是考虑直接从 .tar.gz 中读取
082  * 参数:
083  *      in      - InputStream,注意不能使用 in.close() 方法,因为在函数外部可能还需要继续从 in 读数据
084  * 返回值:
085  *      是否成功
086  */
087     public boolean read(InputStream finthrows Exception {
088 
089         if!"AF1F".equalsIgnoreCase(productSymbologyLayerBlock.PacketCode) ) {//非扫描数据 Radial Image
090             return(false);
091         }
092         boolean ok  = false;
093         radialProductBlock      = new RadialProductBlock();
094         ok  = radialProductBlock.read(fin);
095         ifok && radialProductBlock.NumberOfRadials > ) {
096             radialImageBlock    = new RadialImageBlock[radialProductBlock.NumberOfRadials];
097             for(int i=0;i<radialProductBlock.NumberOfRadials;i++) {
098                 radialImageBlock[inew RadialImageBlock();
099                 ok  = ok && radialImageBlock[i].read(fin);
100             }
101         }
102         return(ok);
103     }
104 
105 /**
106  * 功能:绘制雷达背景图(图形区域为640*480,雷达图形区域为480*480,雷达站点信息区域为160*480)
107  * 参数:
108  *      z       - 缩放系数
109  *      g       - 图形设备
110  *      c       - 雷达中心位置
111  *      pc      - 极圈
112  *      agl     - 径线间隔,非正值则不画径线
113  *      bnd     - 省市县边界
114  * 返回值:
115  *      是否成功
116  */
117     public boolean drawBackground(double z, Graphics2D g, Point c, boolean pc, double agl, boolean bnd) {
118         ifz <= 0.0 ) {
119             return(false);
120         }
121         try {
122             Polar   polar   = new Polar(c, 0.001*productDescriptionBlock.RadarLongitude, 0.001*productDescriptionBlock.RadarLatitude);
123             polar.setScale(1.0*z);
124             //以下两行改进线条的锯齿
125             RenderingHints renderHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
126             g.setRenderingHints(renderHints);
127 
128 //          g.setColor(Color.black);//背景色
129 //          g.fillRect(c.x-(int)(z*240), c.y-(int)(z*240), (int)(z*240*2), (int)(z*240*2));
130 
131             g.setColor(Color.white);//雷达图形区域的边框颜色
132             g.drawRect(c.x-(int)(z*240), c.y-(int)(z*240)(int)(z*240*2)(int)(z*240*2)-2);
133 
134             ifbnd ) {//画行政边界
135                 Coordinate  coordinate  = new Coordinate(polar);
136                 Diamond09.drawBorderline(g, new Color(92,92,92), coordinate, "/GIMDR/gmiss/config/CountyMap.dat");
137                 Diamond09.drawBorderline(g, new Color(160,160,160), coordinate, "/GIMDR/gmiss/config/ProvinceMap.dat");
138             }
139 
140             ifpc ) {//画极圈
141                 g.setColor(new Color(255,255,255));
142                 for(int i=50;i<=200;i=i+50) {//每50公里画一个圈
143                     g.drawArc(c.x-(int)(z*i), c.y-(int)(z*i)(int)(z*i)*2(int)(z*i)*20360);
144                 }
145                 g.drawArc(c.x-(int)(z*240), c.y-(int)(z*240)(int)(z*240)*2(int)(z*240)*20360);//外圈240公里
146             }
147 
148             ifagl >= 1.0 ) {//画极径
149                 Point   pos1, pos2;
150                 for(double i=0.0;i<180.0;i=i+agl) {
151                     pos1    = polar.getXY(z*240.0,   0.0+i);
152                     pos2    = polar.getXY(z*240.0180.0+i);
153                     g.drawLine(pos1.x, pos1.y, pos2.x, pos2.y);
154                 }
155             }
156             return(true);
157         }
158         catch(Exception ex) {
159             System.out.println(ex.getMessage());
160             ex.printStackTrace();
161             return(false);
162         }
163     }
164 
165 /**
166  * 功能:绘制雷达信息区域
167  * 参数:
168  *      g       - 图形设备
169  *      m       - 雷达信息区域左上角位置
170  * 返回值:
171  *      是否成功
172  */
173     public boolean drawInformation(Graphics2D g, Point m) {
174         //以下两行改进线条的锯齿
175         RenderingHints renderHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
176         g.setRenderingHints(renderHints);
177         g.setColor(Color.white);//信息区域的边框颜色
178         g.drawRect(m.x, m.y, 160479);//住处区域的边框
179         return(true);
180     }
181 
182 /**
183  * 功能:绘制雷达产品图,根据不同类型分别调用相应的画图函数
184  * 参数:
185  *      z       - 缩放系数
186  *      g       - 图形设备
187  *      c       - 雷达中心位置
188  * 返回值:
189  *      是否成功
190  */
191     public boolean draw(double z, Graphics2D g, Point c) {
192         return(
193             z <= 0.0 ||
194             null == radialProductBlock ||
195             radialProductBlock.NumberOfRadials <= ||
196             drawRadialImage(z, g, c)
197         );
198     }
199 /**
200  * 功能:绘制RadialImage扫描图像(采用多边形填充法代替弧形填充)
201  * 参数:
202  *      z       - 缩放系数
203  *      g       - 图形设备
204  *      c       - 雷达中心位置
205  * 返回值:
206  *      是否成功
207  */
208     public boolean drawRadialImage(double z, Graphics2D g, Point c) {
209 
210         Polar   polar   = new Polar(c, 0.001*productDescriptionBlock.RadarLongitude, 0.001*productDescriptionBlock.RadarLatitude);
211         polar.setScale(1.0);
212 //背景
213         //以下两行改进线条的锯齿
214         RenderingHints renderHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
215         g.setRenderingHints(renderHints);
216 
217         Point   pos;
218         double  rangeScaleFactor    = 0.001 (int)radialProductBlock.RangeScaleFactor;
219         Polygon p   = new Polygon();
220         for(int i=0;i<radialProductBlock.NumberOfRadials;i++) {
221             int iRunCount   = 0;
222             int iRunValue   = 0;
223             int iColor      = -1;
224             for(int j=0;j<radialImageBlock[i].NumberOfRadialRLE*2;j++) {
225                 iRunValue   = radialImageBlock[i].Data[j>> 0xF;
226                 iColor      = radialImageBlock[i].Data[j0xF;
227                 ifiRunValue > && iColor >= && iColor < 15 && radialImageBlock[i].DeltaAngle > ) {
228                     g.setColor(RadialImage.levels[iColor]);
229                     p.reset();//重置多边形为空
230                     ifiRunCount == ) {
231                         p.addPoint(c.x, c.y);
232                     }
233                     else {
234 /*
235                         //矩形填充
236                         pos = polar.getXY(z*rangeScaleFactor*iRunCount, 0.1*radialImageBlock[index][i].StartAngle);
237                         p.addPoint(pos.x, pos.y);
238                         pos = polar.getXY(z*rangeScaleFactor*iRunCount, 0.1*(radialImageBlock[index][i].StartAngle+radialImageBlock[index][i].DeltaAngle-1));
239                         p.addPoint(pos.x, pos.y);
240 */
241                         for(double k=0.0;k<=0.1*radialImageBlock[i].DeltaAngle-0.1;k=k+0.01) {
242                             pos = polar.getXY(z*rangeScaleFactor*iRunCount, 0.1*radialImageBlock[i].StartAngle+k);
243                             p.addPoint(pos.x, pos.y);
244                         }
245 
246                     }
247 /*
248                     //矩形填充
249                     pos = polar.getXY(z*rangeScaleFactor*(iRunCount+iRunValue), 0.1*(radialImageBlock[index][i].StartAngle+radialImageBlock[index][i].DeltaAngle-1));
250                     p.addPoint(pos.x, pos.y);
251                     pos = polar.getXY(z*rangeScaleFactor*(iRunCount+iRunValue), 0.1*radialImageBlock[index][i].StartAngle);
252                     p.addPoint(pos.x, pos.y);
253 */
254                     //多边形填充
255                     for(double k=0.1*radialImageBlock[i].DeltaAngle-0.1;k>=0.0;k=k-0.01) {
256                         pos = polar.getXY(z*rangeScaleFactor*(iRunCount+iRunValue)0.1*radialImageBlock[i].StartAngle+k);
257                         p.addPoint(pos.x, pos.y);
258                     }
259 
260                     ifp.npoints >= ) {
261 //                      p.addPoint(p.xpoints[0], p.ypoints[0]);
262                         g.fillPolygon(p);//仅填充多边形内部
263                         g.drawPolygon(p);//画多边形边框
264                     }
265                 }
266                 iRunCount   += iRunValue > ? iRunValue : 0;
267             }
268         }
269         return(true);
270     }
271 
272 }

 


RadialImageBlock.java
001 /**
002  * PACKAGE     : cma.gmb.doppler.datatype
003    FILENAME    : RadialImageBlock.java
004  * DESCRIPTION : 多普勒雷达产品数据结构(Radial格式)
005  * AUTHOR      : 刘泽军
006  * EMAIL       : BJ0773@gmail.com
007  * Date        : 2007-06-02 03:47:35
008  * Update      : 2007-06-12
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 RadialImageBlock {//极坐标扫描图像数据
020 
021     public  static  int SIZE    = 6;
022 
023     public  short   NumberOfRadialRLE;
024     public  short   StartAngle;
025     public  short   DeltaAngle;
026     public  byte[]  Data;
027 
028 /**
029  * 功能:构造函数
030  * 参数:
031  *      无
032  * 返回:
033  *      无
034  */
035     public RadialImageBlock() {
036     }
037 
038 /**
039  * 功能:从随机文件中读取数据,并进行BigEndian转换
040  * 参数:
041  *      raf     - 随机访问的文件对象
042  * 返回:
043  *      是否成功
044  */
045     public boolean read(RandomAccessFile raf) {
046         try {
047             byte[]  buf = new byte[RadialImageBlock.SIZE];
048             int     len = raf.read(buf);
049             boolean ok  = len == RadialImageBlock.SIZE ? parse(buf, 0false;
050             ifok && NumberOfRadialRLE > ) {
051                 Data    = new byte[NumberOfRadialRLE*2];
052                 len     = raf.read(Data);
053             }
054             return(ok && len == NumberOfRadialRLE*2);
055         }
056         catch(Exception ex) {
057             return(false);
058         }
059     }
060 
061 /**
062  * 功能:从输入流文件中读取数据,并进行BigEndian转换
063  * 参数:
064  *      in      - InputStream对象
065  * 返回:
066  *      是否成功
067  */
068     public boolean read(InputStream in) {
069         try {
070             byte[]  buf = new byte[RadialImageBlock.SIZE];
071             int     len = in.read(buf);
072             boolean ok  = len == RadialImageBlock.SIZE ? parse(buf, 0false;
073             ifok && NumberOfRadialRLE > ) {
074                 Data    = new byte[NumberOfRadialRLE*2];
075                 len     = in.read(Data);
076             }
077             return(ok && len == NumberOfRadialRLE*2);
078         }
079         catch(Exception ex) {
080             return(false);
081         }
082     }
083 
084 /**
085  * 功能:从缓冲区中读数据
086  *       (在外部方法中,一次性读入所有数据,然后逐类分析数据)
087  * 参数:
088  *      buf     - 缓冲数据
089  *      index   - 偏移
090  * 返回:
091  *      正确读出的数据字节数
092  */
093     public int read(byte[] buf, int index) {
094         boolean ok  = parse(buf, index);
095         ifok && NumberOfRadialRLE > && buf.length >= index+NumberOfRadialRLE*) {
096             Data    = new byte[NumberOfRadialRLE*2];
097             for(int i=0;i<NumberOfRadialRLE*2;i++) {
098                 Data[i= buf[index+i];
099             }
100             return(RadialImageBlock.SIZE+NumberOfRadialRLE*2);
101         }
102         return(0);
103     }
104 
105 /**
106  * 功能:从缓冲区中分析出数据
107  * 参数:
108  *      buf     - 缓冲数据
109  * 返回:
110  *      是否成功
111  */
112     public boolean parse(byte[] buf) {
113         return(parse(buf, 0));
114     }
115 
116 /**
117  * 功能:从缓冲区中分析出数据
118  * 参数:
119  *      buf     - 缓冲数据
120  *      index   - 偏移
121  * 返回:
122  *      是否成功
123  */
124     public boolean parse(byte[] buf, int index) {
125         NumberOfRadialRLE   = DataConverterBE.getShort(buf, index+ 0);
126         StartAngle          = DataConverterBE.getShort(buf, index+ 2);
127         DeltaAngle          = DataConverterBE.getShort(buf, index+ 4);
128         return(true);
129     }
130 
131 /**
132  * 功能:获得数据信息
133  * 参数:
134  *      无
135  * 返回:
136  *      数据信息
137  */
138     public String info() {
139         String  msg =
140             "/nRadialImageBlock.SIZE = " + String.valueOf(RadialImageBlock.SIZE+
141             "/n    NumberOfRadialRLE = " + String.valueOf(NumberOfRadialRLE+
142             "/n    StartAngle        = " + String.valueOf(StartAngle+
143             "/n    DeltaAngle        = " + String.valueOf(DeltaAngle+
144             "/n";
145 /*      for(int i=0;i<NumberOfRadialRLE*2;i++) {
146             msg = msg + String.valueOf((new Byte(Data[i])).intValue()/16)+","+String.valueOf((new Byte(Data[i])).intValue()%16)+" ";
147         }
148         msg = msg + "/n";
149 */
150         return(msg);
151     }
152 /**
153  * 功能:打印数据,主要用于测试
154  * 参数:
155  *      无
156  * 返回:
157  *      无
158  */
159     public void print() {
160         System.out.println(info());
161     }
162 
163 }

 


RadialProductBlock.java
001 /**
002  * PACKAGE     : cma.gmb.doppler.datatype
003    FILENAME    : RadialProductBlock.java
004  * DESCRIPTION : 多普勒雷达产品数据结构(Radial格式)
005  * AUTHOR      : 刘泽军
006  * EMAIL       : BJ0773@gmail.com
007  * Date        : 2007-06-07 11:01:44
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 RadialProductBlock {//层数据包
020 
021     public  static  int SIZE    = 12;
022 
023     public  short   IndexOfFirstRangeBin;
024     public  short   NumberOfRangeBins;
025     public  short   CenterOfSweepI;
026     public  short   CenterOfSweepJ;
027     public  short   RangeScaleFactor;
028     public  short   NumberOfRadials;
029 
030 /**
031  * 功能:构造函数
032  * 参数:
033  *      无
034  * 返回:
035  *      无
036  */
037     public RadialProductBlock() {
038     }
039 
040 /**
041  * 功能:从文件中读取数据,并进行BigEndian转换
042  * 参数:
043  *      raf     - 随机访问的文件对象
044  * 返回:
045  *      是否成功
046  */
047     public boolean read(RandomAccessFile raf) {
048         try {
049             byte[]  buf = new byte[RadialProductBlock.SIZE];
050             int     len = raf.read(buf);
051             return(len == RadialProductBlock.SIZE ? parse(buf, 0false);
052         }
053         catch(Exception ex) {
054             return(false);
055         }
056     }
057 
058 /**
059  * 功能:从输入流文件中读取数据,并进行BigEndian转换
060  * 参数:
061  *      in      - InputStream对象
062  * 返回:
063  *      是否成功
064  */
065     public boolean read(InputStream in) {
066         try {
067             byte[]  buf = new byte[RadialProductBlock.SIZE];
068             int     len = in.read(buf);
069             return(len == RadialProductBlock.SIZE ? parse(buf, 0false);
070         }
071         catch(Exception ex) {
072             return(false);
073         }
074     }
075 
076 /**
077  * 功能:从缓冲区中读数据
078  *       (在外部方法中,一次性读入所有数据,然后逐类分析数据)
079  * 参数:
080  *      buf     - 缓冲数据
081  *      index   - 偏移
082  * 返回:
083  *      正确读出的数据字节数
084  */
085     public int read(byte[] buf, int index) {
086         return(parse(buf, index)?RadialProductBlock.SIZE:0);
087     }
088 
089 /**
090  * 功能:从缓冲区中分析出数据
091  * 参数:
092  *      buf     - 缓冲数据
093  * 返回:
094  *      是否成功
095  */
096     public boolean parse(byte[] buf) {
097         return(parse(buf, 0));
098     }
099 
100 /**
101  * 功能:从缓冲区中分析出数据
102  * 参数:
103  *      buf     - 缓冲数据
104  *      index   - 偏移
105  * 返回:
106  *      是否成功
107  */
108     public boolean parse(byte[] buf, int index) {
109         IndexOfFirstRangeBin    = DataConverterBE.getShort(buf, index+ 0);
110         NumberOfRangeBins       = DataConverterBE.getShort(buf, index+ 2);
111         CenterOfSweepI          = DataConverterBE.getShort(buf, index+ 4);
112         CenterOfSweepJ          = DataConverterBE.getShort(buf, index+ 6);
113         RangeScaleFactor        = DataConverterBE.getShort(buf, index+ 8);
114         NumberOfRadials         = DataConverterBE.getShort(buf, index+10);
115         return(true);
116     }
117 
118 /**
119  * 功能:获得数据信息
120  * 参数:
121  *      无
122  * 返回:
123  *      数据信息
124  */
125     public String info() {
126         String  msg =
127             "/nRadialProductBlock.SIZE  = " + String.valueOf(RadialProductBlock.SIZE+
128             "/n    IndexOfFirstRangeBin = " + String.valueOf(IndexOfFirstRangeBin+
129             "/n    NumberOfRangeBins    = " + String.valueOf(NumberOfRangeBins+
130             "/n    CenterOfSweepI       = " + String.valueOf(CenterOfSweepI+
131             "/n    CenterOfSweepJ       = " + String.valueOf(CenterOfSweepJ+
132             "/n    RangeScaleFactor     = " + String.valueOf(RangeScaleFactor+
133             "/n    NumberOfRadials      = " + String.valueOf(NumberOfRadials+
134             "/n";
135         return(msg);
136     }
137 
138 /**
139  * 功能:打印数据,主要用于测试
140  * 参数:
141  *      无
142  * 返回:
143  *      无
144  */
145     public void print() {
146         System.out.println(info());
147     }
148 
149 }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值