当前位置: 首页 > 工具软件 > Mercator POS > 使用案例 >

Mercator(麦卡托)等角圆柱投影--多用于赤道和低纬地区

何博涛
2023-12-01

Mercator.java
001  /*
002 
003     Mercator 麦卡脱投影
004 
005        PACKAGE: cma.common.projection
006       FILENAME: Mercator.java
007       LANGUAGE: Java2 v1.4
008       ORIGINAL: none
009    DESCRIPTION:
010         CREATE: 2007-07-08 13:22:39
011         UPDATE: 2007-07-18
012         AUTHOR: 刘泽军 (BJ0773@gmail.com)
013                 广西气象减灾研究所
014                 Guangxi Institude of Meteorology and Disaster-reducing Research(GIMDR)
015      REFERENCE: http://mathworld.wolfram.com/MercatorProjection.html
016 
017        Compile: javac Coordinate.java Mercator.java
018  */
019 
020  package  cma.common.projection;
021 
022  import  java.io.*;
023  import  java.awt.*;
024  import  java.awt.geom.*;
025  import  java.util.*;
026  import  java.lang.Math.*;
027  import  java.text.DecimalFormat;
028 
029  public class  Mercator  extends  Coordinate  {
030 
031  /**
032    * 功能:
033    *      重置参数
034    * 参数:
035    *      lon,lat     - 中心经纬度,
036    *      px,py       - 中心经纬度对应的屏幕坐标
037    *      sx,sy       - 缩放系数
038    * 返回值:
039    *      无
040    */
041       public  void  reset ( double  lon,  double  lat,  int  px,  int  py,  double  sc ) {
042           type            = Coordinate.MERCATOR;
043           center          =  new  Point2D.Double (
044                           lon <    0.0  ?    0.0  : lon >  360.0  360.0  : lon,
045                           lat <=- 90.0  ?    0.0  : lat >=  90.0  ?    0.0  : lat
046                       ) ;
047           place           =  new  Point ( px, py ) ;
048           scaleXY         =  new  Point2D.Double ( 7.25 433.0 ) ; //与Micaps1.0版匹配的参数
049           scale           = sc ==  0.0  1.0  : Math.abs ( sc ) ;;
050           scaleOriginal   = scale;
051           offset          =  new  Point ( 0 0 ) ; //未用
052       }
053 
054  /**
055    * 功能:
056    *      构造函数
057    * 参数:
058    *      无(使用缺省值)
059    * 返回值:
060    *      无
061    */
062       public  Mercator () {
063           reset ( 109.40 24.35 640 480 1.0 ) ;
064       }
065 
066  /**
067    * 功能:
068    *      构造函数
069    * 参数:
070    *      lon,lat     - 中心经纬度,
071    *      px,py       - 中心经纬度对应的屏幕坐标
072    *      sc          - 缩放系数
073    * 返回值:
074    *      无
075    */
076       public  Mercator ( double  lon,  double  lat,  int  px,  int  py,  double  sc ) {
077           reset ( lon, lat, px, py, sc ) ;
078       }
079 
080  /**
081    * 功能:
082    *      获得屏幕坐标
083    * 参数:
084    *      lon     - 经度
085    *      lat     - 纬度
086    * 返回值:
087    *      屏幕坐标
088    */
089       public  Point getPosition ( double  lon,  double  lat ) {
090           if lat >=  90.0  || lat <= - 90.0  ) {
091               return ( null ) ;
092           }
093           double   x   = scale*scaleXY.x* ( lon-center.x + place.x;
094           double   y1  = Math.log ( Math.tan ( Math.toRadians ( center.y )) + 1.0 /Math.cos ( Math.toRadians ( center.y ))) ;
095           double   y2  = Math.log ( Math.tan ( Math.toRadians ( lat )) + 1.0 /Math.cos ( Math.toRadians ( lat ))) ;
096           double   y   = scale*scaleXY.y * ( y1-y2 + place.y;
097           return (
098               new  Point (
099                   ( int )( x+ 0.5 ) ,
100                   ( int )( y+ 0.5 )
101               )
102           ) ;
103       }
104 
105  /**未完成
106    * 功能:
107    *      获得屏幕坐标对应的经纬度
108    * 参数:
109    *      x       - 屏幕水平坐标
110    *      y       - 屏幕垂直坐标
111    * 返回值:
112    *      对应的经纬度
113    */
114       public  Point2D.Double getCoordinate ( int  x,  int  y ) {
115           double   y1  = Math.log ( Math.tan ( Math.toRadians ( center.y )) + 1.0 /Math.cos ( Math.toRadians ( center.y ))) ;
116           double   y2  = y1 -  ( y - place.y / scale / scaleXY.y;
117  /*
118  double  y2  = Math.log(Math.tan(Math.toRadians(lat))+1.0/Math.cos(Math.toRadians(lat)));
119  exp(y2)=tan(lat)+1.0/cos(lat)
120  exp(y2)=(sin(lat)+1)/sqrt(1-sin(lat)*sin(lat))
121  1-sin(lat)*sin(lat)=(1+sin(lat))*(1+sin(lat))/(exp(y2)*exp(y2))
122  (1-sin(lat))=(1+sin(lat))/(exp(y2)*exp(y2))
123  1.0/(exp(y2)*exp(y2))+sin(lat)/(exp(y2)*exp(y2))+sin(lat)-1=0;
124  sin(lat)*(1.0+1.0/(exp(y2)*exp(y2)))=1.0-1.0/(exp(y2)*exp(y2))
125  sin(lat)*(exp(y2)*exp(y2)+1)=(exp(y2)*exp(y2)-1)
126  sin(lat)=(exp(y2)*exp(y2)-1)/(exp(y2)*exp(y2)+1)
127 
128  */
129           double   lon =  ( x - place.x / scale/scaleXY.x + center.x;
130           double   lat = Math.toDegrees ( Math.asin (( Math.exp ( y2 ) *Math.exp ( y2 ) - 1 ) / ( Math.exp ( y2 ) *Math.exp ( y2 ) + 1 ))) ;
131           return (
132               new  Point2D.Double (
133                   lon,
134                   lat
135               )
136           ) ;
137       }
138 
139  /**
140    * 功能:
141    *      画经线、纬线
142    * 参数:
143    *      g       - 图形设备
144    *      f       - 字体
145    *      c       - 画线颜色
146    *      inc_lon - 经线间隔
147    *      inc_lat - 纬线间隔
148    * 返回值:
149    *      无
150    */
151       public  void  drawGridLine ( Graphics2D g, Font f, Color c,  int  inc_lon,  int  inc_lat ) {
152 
153           DecimalFormat   df  =  new  DecimalFormat ( "0.#" ) ;
154           Color   saveColor   = g.getColor () ;
155           Font    saveFont    = g.getFont () ;
156           g.setColor ( c ) ;
157           g.setFont ( null ==f?f: new  Font ( "Times New Roman" , Font.PLAIN,  12 )) ;
158           FontMetrics fm  = g.getFontMetrics () ;
159           String      text;
160           byte         tmpByte [] ;
161           int          bytesWidth, bytesHeight = fm.getHeight () ;;
162           Point       pos1, pos2;
163           if inc_lon >  ) {
164               for ( double  lon= 0.0 ;lon<= 360.0 ;lon=lon+inc_lon ) {
165                   if 180.0  == lon  ) {
166                       for ( double  lat=- 90.0 +inc_lat;lat<= 90.0 -inc_lat;lat=lat+inc_lat ) {
167                           text        = df.format ( lat ) ;
168                           tmpByte     = text.getBytes () ;
169                           bytesWidth  = fm.bytesWidth ( tmpByte,  0 , tmpByte.length ) ;
170                           pos1    =  this .getPosition ( lon, lat ) ;
171                           g.drawString ( text, pos1.x-bytesWidth/ 2 , pos1.y+bytesHeight/ 3 ) ;
172                       }
173                   }
174                   pos1    =  this .getPosition ( lon, - 90.0 +inc_lat ) ;
175                   pos2    =  this .getPosition ( lon,   90.0 -inc_lat ) ;
176                   g.drawLine ( pos1.x, pos1.y, pos2.x, pos2.y ) ;
177               }
178           }
179           if inc_lat >  ) {
180               for ( double  lat=- 90.0 +inc_lat;lat<= 90.0 -inc_lat;lat=lat+inc_lat ) {
181                   if 0.0  == lat  ) {
182                       for ( double  lon= 0.0 ;lon<= 360.0 ;lon=lon+inc_lon ) {
183                           text        = df.format ( lon ) ;
184                           tmpByte     = text.getBytes () ;
185                           bytesWidth  = fm.bytesWidth ( tmpByte,  0 , tmpByte.length ) ;
186                           pos1    =  this .getPosition ( lon, lat ) ;
187                           g.drawString ( text, pos1.x-bytesWidth/ 2 , pos1.y+bytesHeight/ 3 ) ;
188                       }
189                   }
190                   pos1    =  this .getPosition (   0.0 , lat ) ;
191                   pos2    =  this .getPosition ( 360.0 , lat ) ;
192                   g.drawLine ( pos1.x, pos1.y, pos2.x, pos2.y ) ;
193               }
194           }
195           g.setFont ( saveFont ) ;
196           g.setColor ( saveColor ) ;
197       }
198  }
 类似资料: