Lambert.java


001  /**
002 
003     Lambert兰勃特投影
004 
005        PACKAGE: cma.common.projection
006       FILENAME: Lambert.java
007       LANGUAGE: Java2 v1.4
008       ORIGINAL: 最初由成气院向卫国袁东升老师编写,但与Micaps1.0的兰勃特投影不一致,距离标准经度远的地方误差增大。
009    DESCRIPTION: Lambert projection coordinate
010         CREATE: 2003-03-06 00:31:21
011         UPDATE: 2007-07-17 根据 http://mathworld.wolfram.com  提供的公式重新编写
012         AUTHOR: 刘泽军 (BJ0773@gmail.com)
013                 广西气象减灾研究所
014                 Guangxi Institude of Meteorology and Disaster-reducing Research(GIMDR)
015      REFERENCE: http://mathworld.wolfram.com/LambertConformalConicProjection.html
016 
017        COMPILE: javac Coordinate.java Lambert.java
018 
019  ********** 重写后,与Micaps1.0版的“T-兰勃脱投影”完全一致! **********
020 
021        HISTORY:
022           0、lbt.cpp,两位老师的源代码
023           1、CCoordinate.cpp,线性和Lambert投影,主要用于FY-2B卫星云图定位和Micaps交互;
024           2、CRotateCoordinate.cpp,坐标旋转,主要是用于柳州Doppler雷达选址时从扫描的军用地图中定位及读取高程信息);
025           3、CLambert.cpp、CLines.cpp,各投影代码独立为类
026           4、Lambert.java,兰勃托投影改写为JAVA版
027           5、Lambert.java,2007-07-17重新编写
028 
029  **/
030 
031  package  cma.common.projection;
032 
033  import  java.io.*;
034  import  java.awt.*;
035  import  java.awt.geom.*;
036  import  java.util.*;
037  import  java.lang.Math.*;
038  import  java.text.DecimalFormat;
039 
040  import  cma.common.atmos.*;
041 
042  public class  Lambert  extends  Coordinate  {
043 
044       //private   double  fn = 0.715566799999999;
045       private  double   F;
046       private  double   n;
047       private  double   p0;
048 
049       private  void  reset ( //Degree
050               double   standardLon,     double   standardLat,
051               double   positionLon,     double   positionLat,
052               int      positionHori,    int      positionVert,
053               double   zoomIndex ) {
054           type            = Coordinate.LAMBERT;
055           standard        =  new  Point2D.Double ( Math.IEEEremainder ( Math.abs ( standardLon ) ,  360.0 ) ,  0.0 ) ;
056           center          =  new  Point2D.Double ( Math.IEEEremainder ( Math.abs ( positionLon ) ,  360.0 ) , positionLat < - 85.0  ? - 85.0  : positionLat >  85.0  ?  85.0  : positionLat ) ;
057           place           =  new  Point ( positionHori, positionVert ) ;
058           scale           = zoomIndex <=  0.0  ?  1.0  : zoomIndex;
059           scaleOriginal   = scale;
060 
061           double   lat1= Math.toRadians ( 30.0 ) , lat2 = Math.toRadians ( 60.0 ) ; //标准纬度
062           double   lat3= Math.toRadians ( 45.0 + 30.0 / 2.0 ) , lat4 = Math.toRadians ( 45.0 + 60.0 / 2 ) ; //标准纬度
063           double   lat5= Math.toRadians ( 45.0 +center.y/ 2.0 ) ,  lat6 = Math.toRadians ( 45.0 +standard.y/ 2.0 ) ;
064           n   = Math.log ( Math.cos ( lat1 ) /Math.cos ( lat2 )) /Math.log ( Math.tan ( lat4 ) /Math.tan ( lat3 )) ;
065           F   = scale *  484.96  * Math.cos ( lat1 ) *Math.pow ( Math.tan ( lat3 ) ,n ) /n; //484.96为根据Micaps1.0拟合得到的数值
066           p0  = F * Math.pow ( 1.0 /Math.tan ( lat6 ) ,n ) ;
067           double   r   = Math.toRadians ( n* ( center.x-standard.x )) ;
068           double   p   = F * Math.pow ( 1.0 /Math.tan ( lat5 ) ,n ) ;
069           double   x   = p * Math.sin ( r ) ;
070           double   y   = p * Math.cos ( r )  - p0;
071           offset      =  new  Point (( int )( 0.5  + place.x - x ) ,  ( int )( 0.5  + place.y - y )) ;
072       }
073 
074       public  Lambert () {
075           reset (
076               110.0 ,   30.0 ,
077               110.0 ,   35.0 ,
078               512 ,     384 ,
079               1
080           ) ;
081       }
082 
083       public  Lambert ( //Degree
084               double   standardLon,     double   standardLat,
085               double   positionLon,     double   positionLat,
086               int      positionHori,    int      positionVert,
087               double   zoomIndex ) {
088           reset (
089               standardLon,standardLat,
090               positionLon,    positionLat,
091               positionHori,   positionVert,
092               zoomIndex
093           ) ;
094       }
095 
096       public  Lambert ( //Degree
097               double   positionLon,     double   positionLat,
098               int      positionHori,    int      positionVert,
099               double   zoomIndex ) {
100           reset (
101               110.0 ,       30.0 ,
102               positionLon,    positionLat,
103               positionHori,   positionVert,
104               zoomIndex
105           ) ;
106       }
107 
108  /**
109    * 功能:获得屏幕坐标
110    * 参数:
111    *      lon     - 经度值(度)
112    *      lat     - 纬度值(度)
113    * 返回值:
114    *      屏幕坐标
115    */
116       public  Point getPosition ( double  lon,  double  lat ) {
117           double   lat5= Math.toRadians ( 45.0 +lat/ 2.0 ) ;
118           double   r   = Math.toRadians ( n* ( lon-standard.x )) ;
119           double   p   = F * Math.pow ( 1.0 /Math.tan ( lat5 ) ,n ) ;
120           double   x   = p * Math.sin ( r ) ;
121           double   y   = p * Math.cos ( r )  - p0;
122           return ( new  Point (( int )( 0.5  + offset.x + x ) ,  ( int )( 0.5  + offset.y + y ))) ;
123       }
124 
125  /**
126    * 功能:获得经纬度坐标
127    * 参数:
128    *  xScreen     - 屏幕坐标值(x方向)
129    *  yScreen     - 屏幕坐标值(y方向)
130    * 返回值:
131    *      经纬度坐标
132    */
133       public  Point2D.Double getCoordinate ( int  x,  int  y ) {
134 
135           double   lon, lat, r;
136           if (  y-offset.y+p0 ==  0  ) {
137               lon = standard.x+ 45.0 /n;
138               lat =  2.0 * ( Math.toDegrees ( Math.atan ( 1.0 /Math.pow (( x-offset.x ) /F, 1.0 /n ))) - 45.0 ) ;
139           }
140           else  {
141               lon = standard.x + Math.toDegrees ( Math.atan (( x-offset.x ) / ( y-offset.y+p0 ))) /n;
142               r   = Math.toRadians ( n* ( lon-standard.x )) ;
143               lat =  2.0 * ( Math.toDegrees ( Math.atan ( 1.0 /Math.pow (( y-offset.y+p0 ) /Math.cos ( r ) /F, 1.0 /n ))) - 45.0 ) ;
144           }
145           return ( new  Point2D.Double ( lon,lat )) ;
146       }
147 
148  /**
149    * 功能:获得相对于标准经度的偏角
150    * 参数:
151    *  degreeLon   - 经度值
152    *  degreeLat   - 纬度值
153    * 返回值:
154    *      偏角
155    */
156       public  double  getAngle ( double  degreeLon,  double  degreeLat ) {
157           if (  9999.0  <= degreeLat || - 9999.0  >= degreeLat ||  90.0  == degreeLat || - 90.0  == degreeLat  ) {
158               return ( 0.0 ) ;
159           }
160           Point   xy1     = getPosition ( standard.x,  90.0 ) ;
161           Point   xy2     = getPosition ( degreeLon, degreeLat ) ;
162           double   x1      = xy1.x;
163           double   y1      = xy1.y;
164           double   x2      = xy2.x;
165           double   y2      = xy2.y;
166           double   rotateAngle =  0.0 ;
167           if (  x2 == x1  ) {
168               rotateAngle = y2 >= y1 ?  0.0  :  180.0 ;
169           }
170           else if (  y1 == y2  ) {
171               rotateAngle = x2 >= x1 ?  270.0  :  90.0 ;
172           }
173           else  { //分象限判断旋转角度,坐标原点在xy1
174               double   deltaY      = Math.abs ( y2 - y1 ) ;
175               double   r           = Math.sqrt (( x2 - x1 ) * ( x2 - x1 )  +  ( y2 - y1 ) * ( y2 - y1 )) ;
176               double   angelDegree = Math.toDegrees ( Math.asin ( deltaY/r )) ;
177               if (  x2 > x1 && y2 > y1  ) {
178                   rotateAngle = - 90.0  + angelDegree;
179               }
180               else if (  x2 > x1 && y2 < y1  ) {
181                   rotateAngle = - 90.0  - angelDegree;
182               }
183               else if (  x2 < x1 && y2 < y1  ) {
184                   rotateAngle =  90.0  + angelDegree;
185               }
186               else if (  x2 < x1 && y2 > y1  ) {
187                   rotateAngle =  90.0  - angelDegree;
188               }
189               else  {
190                   return ( Algorithm.DefaultValue ) ;
191               }
192           }
193           return ( rotateAngle ) ;
194       }
195 
196  /**
197    * 功能:
198    *      画经线、纬线
199    * 参数:
200    *      g       - 图形设备
201    *      f       - 字体
202    *      c       - 画线颜色
203    *      inc_lon - 经线间隔
204    *      inc_lat - 纬线间隔
205    * 返回值:
206    *      无
207    */
208       public  void  drawGridLine ( Graphics2D g, Font f, Color c,  int  inc_lon,  int  inc_lat ) {
209 
210           DecimalFormat   df  =  new  DecimalFormat ( "0.#" ) ;
211           Color   saveColor   = g.getColor () ;
212           Font    saveFont    = g.getFont () ;
213           g.setColor ( c ) ;
214           g.setFont ( null ==f?f: new  Font ( "Times New Roman" , Font.PLAIN,  12 )) ;
215           Point       xy, xy1;
216           double       rotateAngle;
217           FontMetrics fm  = g.getFontMetrics () ;
218           String      text;
219           byte         tmpByte [] ;
220           int          bytesWidth, bytesHeight = fm.getHeight () ;;
221           g.setColor ( c ) ;
222           Point   pos1, pos2;
223           //画纬线
224           for ( int  lat= 80 ;lat>=- 80 +inc_lat;lat=lat-inc_lat ) {
225               for ( int  lon= 0 ;lon< 360 ;lon++ ) {
226                   pos1    = getPosition ( lon, lat ) ;
227                   pos2    = getPosition ( lon+ 1 , lat ) ;
228                   g.drawLine ( pos1.x, pos1.y, pos2.x, pos2.y ) ;
229                   if (  lon %  90  ==  0  ) {
230                       g.translate ( pos1.x, pos1.y ) ;
231                       rotateAngle = getAngle ( lon, lat ) ;
232                       if (  rotateAngle != Algorithm.DefaultValue  ) {
233                           g.rotate ( Math.toRadians ( rotateAngle )) ;   //偏角
234                       }
235                       text        = df.format ( lat ) ;
236                       tmpByte     = text.getBytes () ;
237                       bytesWidth  = fm.bytesWidth ( tmpByte,  0 , tmpByte.length ) ;
238                       g.drawString ( text, -bytesWidth/ 2 , bytesHeight/ 3 ) ; //标纬度值
239                       if (  rotateAngle != Algorithm.DefaultValue  ) {
240                           g.rotate ( Math.toRadians ( -rotateAngle )) ;  //偏角
241                       }
242                       g.translate ( -pos1.x, -pos1.y ) ;
243                   }
244               }
245           }
246           //画经线
247           for ( int  lon= 0 ;lon<= 360 ;lon=lon+inc_lon ) {
248               pos1    = getPosition ( lon,   80.0 ) ;
249               pos2    = getPosition ( lon, - 80.0 ) ;
250               g.drawLine ( pos1.x, pos1.y, pos2.x, pos2.y ) ;
251               pos1    = getPosition ( lon,    0.0 ) ;
252               g.translate ( pos1.x, pos1.y ) ;
253               rotateAngle = getAngle ( lon,  0.0 ) ;
254               if (  rotateAngle != Algorithm.DefaultValue  ) {
255                   g.rotate ( Math.toRadians ( rotateAngle )) ;   //偏角
256               }
257               text        = df.format ( lon ) ;
258               tmpByte     = text.getBytes () ;
259               bytesWidth  = fm.bytesWidth ( tmpByte,  0 , tmpByte.length ) ;
260               g.drawString ( text, -bytesWidth/ 2 , bytesHeight/ 3 ) ; //标纬度值
261               if (  rotateAngle != Algorithm.DefaultValue  ) {
262                   g.rotate ( Math.toRadians ( -rotateAngle )) ;  //偏角
263               }
264               g.translate ( -pos1.x, -pos1.y ) ;
265           }
266           g.setFont ( saveFont ) ;
267           g.setColor ( saveColor ) ;
268       }
269  }

Lambert(兰勃托)投影--我国天气图底图广泛采用的一种投影相关推荐

  1. 横轴墨卡托投影参数_几种投影的主要参数【转】

    Gauss Kruger(高斯-克吕格投影):除中央经线和赤道为直线外,其他经线均为对称于中央经线的曲线.该投影没有角度变形,在长度和面积上变形也很小,中央经线无变形,自中央经线向投影带边缘,变形逐渐 ...

  2. [GIS] 常见地图投影 - 投影坐标系 - UTM|高斯克吕格|兰勃特等角投影|墨卡托投影

    文章目录 我国常见的地图投影情况 墨卡托投影 特征 适用 通用横轴墨卡托投影UTM 用途 类型 特点 座标编排 兰勃特等角投影 特点 适用 高斯-克吕格投影 形成条件 特点 适用 分带 6度带 3度带 ...

  3. C#绘制中国地图(兰勃特、墨卡托投影)

    C#绘制中国地图(兰勃特.墨卡托投影) 话不多说,直接上代码: public partial class Form1 : Form{List<PointP> points = new Li ...

  4. 几种投影的特点及分带方法

    一.只谈比较常用的几种:"墨卡托投影"."高斯-克吕格投影"."UTM投影"."兰勃特等角投影" 1. 墨卡托(Merc ...

  5. 图像坐标球面投影_比较常用的坐标几种投影

    只谈比较常用的几种: " 墨卡托投影 " . " 高斯 - 克吕格投影 " . "UTM 投影 " . " 兰勃特 等角投影 &q ...

  6. python地图坐标系转换(bd09,gcj02,wgs84三种投影坐标系相互转化)

    1.介绍 1.1 GIS之坐标系 坐标系是GIS的重中之重,一般来说,工作底图平面坐标系应采用国家大地坐标系CGCS2000(或相当于精度WGS84坐标系),投影方式采用高斯-克吕格投影,高程基准采用 ...

  7. 使用Python,Open3D对点云散点投影到面上并可视化,使用3种方法计算面的法向量及与平均法向量的夹角

    使用Python,Open3D对点云散点投影到面上并可视化,使用3种方法计算面的法向量及与平均法向量的夹角 写这篇博客源于博友的提问,他坚定了我继续坚持学习的心,带给了我充实与快乐. 将介绍以下5部分 ...

  8. 线性代数 --- 投影Projection 六(向量在子空间上的投影)

    向量b在多维子空间上的投影 回顾:任意向量b在另一个向量上(直线上)的投影 在研究向量在子空间上的投影前,先回顾一下前面学习的一个任意向量b在另一个向量a上的投影,共三个部分. 1,求权重系数(A c ...

  9. 地球坐标系与投影方式的理解(关于北京54,西安80,WGS84;高斯,兰勃特,墨卡托投影)

    一.地球模型 地球是一个近似椭球体,测绘时用椭球模型逼近,这个模型叫做参考椭球,如下图: 赤道是一个半径为a的近似圆,任一圈经线是一个半径为b的近似圆.a称为椭球的长轴半径,b称为椭球的短轴半径. a ...

最新文章

  1. 教你如何编写第一个爬虫
  2. mysql数据库名虚拟机_linux虚拟机上装mysql数据库
  3. linux系统photoshop安装教程,在ubuntu中安装photoshop cs6
  4. discuz 删除系统自带的附件上传
  5. Linux 系统上出现^H
  6. Linux下Samba服务器搭建
  7. 第三章 组装个人计算机
  8. IE6 透明遮挡falsh解决方案
  9. C++ 函数模板与分离编译模式
  10. HDU1753 大明A+B
  11. 调整Virtual Box硬盘大小
  12. 基于神经网络多层感知器的波士顿房价数据集回归问题
  13. QT 科学计算器与谷歌拼音输入法实现
  14. 数据分析-因果分析业务实践详解
  15. C#winform图片、图标操作
  16. 【安装】nodesj的addon模块配置使用报错处理
  17. python 跳跃游戏
  18. 安卓手机扫二维码从FTP服务器下载apk
  19. 用express和vue构建全栈项目myweb
  20. Windows系统性能提升方法

热门文章

  1. java scp 上传文件_java基于Scp实现Linux下远程获取、上传文件
  2. 【用VSCode编写MarkDown并导出Epub电子书】
  3. SMC 真空发生器 ZK2A 电气接线接气方法
  4. 浅谈FRVT人脸识别测评
  5. WayOs 帐号到期自动清理工具,致浪费在清理到期用户的青春
  6. ESB产品调用场景分析
  7. 爬虫与反爬虫(斗智斗勇)
  8. Hourglass Network 沙漏网络 (pose estimation姿态估计)
  9. 人工智能的本质居然是……网瘾少年?
  10. 精巧结构设计PDF版