Lambert(兰勃托)投影--我国天气图底图广泛采用的一种投影
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(兰勃托)投影--我国天气图底图广泛采用的一种投影相关推荐
- 横轴墨卡托投影参数_几种投影的主要参数【转】
Gauss Kruger(高斯-克吕格投影):除中央经线和赤道为直线外,其他经线均为对称于中央经线的曲线.该投影没有角度变形,在长度和面积上变形也很小,中央经线无变形,自中央经线向投影带边缘,变形逐渐 ...
- [GIS] 常见地图投影 - 投影坐标系 - UTM|高斯克吕格|兰勃特等角投影|墨卡托投影
文章目录 我国常见的地图投影情况 墨卡托投影 特征 适用 通用横轴墨卡托投影UTM 用途 类型 特点 座标编排 兰勃特等角投影 特点 适用 高斯-克吕格投影 形成条件 特点 适用 分带 6度带 3度带 ...
- C#绘制中国地图(兰勃特、墨卡托投影)
C#绘制中国地图(兰勃特.墨卡托投影) 话不多说,直接上代码: public partial class Form1 : Form{List<PointP> points = new Li ...
- 几种投影的特点及分带方法
一.只谈比较常用的几种:"墨卡托投影"."高斯-克吕格投影"."UTM投影"."兰勃特等角投影" 1. 墨卡托(Merc ...
- 图像坐标球面投影_比较常用的坐标几种投影
只谈比较常用的几种: " 墨卡托投影 " . " 高斯 - 克吕格投影 " . "UTM 投影 " . " 兰勃特 等角投影 &q ...
- python地图坐标系转换(bd09,gcj02,wgs84三种投影坐标系相互转化)
1.介绍 1.1 GIS之坐标系 坐标系是GIS的重中之重,一般来说,工作底图平面坐标系应采用国家大地坐标系CGCS2000(或相当于精度WGS84坐标系),投影方式采用高斯-克吕格投影,高程基准采用 ...
- 使用Python,Open3D对点云散点投影到面上并可视化,使用3种方法计算面的法向量及与平均法向量的夹角
使用Python,Open3D对点云散点投影到面上并可视化,使用3种方法计算面的法向量及与平均法向量的夹角 写这篇博客源于博友的提问,他坚定了我继续坚持学习的心,带给了我充实与快乐. 将介绍以下5部分 ...
- 线性代数 --- 投影Projection 六(向量在子空间上的投影)
向量b在多维子空间上的投影 回顾:任意向量b在另一个向量上(直线上)的投影 在研究向量在子空间上的投影前,先回顾一下前面学习的一个任意向量b在另一个向量a上的投影,共三个部分. 1,求权重系数(A c ...
- 地球坐标系与投影方式的理解(关于北京54,西安80,WGS84;高斯,兰勃特,墨卡托投影)
一.地球模型 地球是一个近似椭球体,测绘时用椭球模型逼近,这个模型叫做参考椭球,如下图: 赤道是一个半径为a的近似圆,任一圈经线是一个半径为b的近似圆.a称为椭球的长轴半径,b称为椭球的短轴半径. a ...
最新文章
- 教你如何编写第一个爬虫
- mysql数据库名虚拟机_linux虚拟机上装mysql数据库
- linux系统photoshop安装教程,在ubuntu中安装photoshop cs6
- discuz 删除系统自带的附件上传
- Linux 系统上出现^H
- Linux下Samba服务器搭建
- 第三章 组装个人计算机
- IE6 透明遮挡falsh解决方案
- C++ 函数模板与分离编译模式
- HDU1753 大明A+B
- 调整Virtual Box硬盘大小
- 基于神经网络多层感知器的波士顿房价数据集回归问题
- QT 科学计算器与谷歌拼音输入法实现
- 数据分析-因果分析业务实践详解
- C#winform图片、图标操作
- 【安装】nodesj的addon模块配置使用报错处理
- python 跳跃游戏
- 安卓手机扫二维码从FTP服务器下载apk
- 用express和vue构建全栈项目myweb
- Windows系统性能提升方法