城建座標與經緯度轉換工具
阿新 • • 發佈:2018-11-25
核心部分底層原始碼
CoodinateCover.java
package PkgCover; import java.io.PrintStream; public class CoodinateCover { private GaussProjection _GP; private double _X; private double _Y; private double _B; private double _L; private String _ErrMsg; private enumLocalCoordinateSys _lcs; public static void main(String[] args) { CoodinateCover CC = new CoodinateCover(3, enumEllipseSys.WGS84, enumLocalCoordinateSys.BeiJingCJ); if (!CC.FunCover(39.976732200000001D, 116.41657351000001D).booleanValue()) { System.out.println("出現錯誤!" + CC.get_ErrMsg()); } System.out.println("經緯度座標(40.2321880683303, 116.523973513395)轉換為城建座標(" + CC.get_X() + ",Y座標:" + CC.get_Y() + ")"); if (!CC.FunAntiCover(CC.get_X(), CC.get_Y()).booleanValue()) { System.out.println("出現錯誤!" + CC.get_ErrMsg()); } System.out.println("反轉後為:緯度為:" + CC.get_B() + ",經度為:" + CC.get_L()); } public CoodinateCover(int zoneWide, enumEllipseSys ellipse, enumLocalCoordinateSys lcs) { this._lcs = lcs; this._GP = new GaussProjection(ellipse, zoneWide); } public Boolean FunCover(double B, double L) { if (!this._GP.Projection(B, L, 0.0D).booleanValue()) { this._ErrMsg = ("高斯投影失敗:" + this._GP.get_ErrMsg()); return Boolean.valueOf(false); } FPData oFPData; FPData oFPData; switch (this._lcs) { case BeiJingCJ: LocalCoordinateSys LCS = new BeiJingCJ(); oFPData = LCS.getFPData(true, this._GP.get_Maridian()); break; default: oFPData = null; } if (oFPData == null) { this._ErrMsg = "沒有例項化FPData物件"; return Boolean.valueOf(false); } this._X = (oFPData.get_X() + oFPData.get_K() * this._GP.get_X() * Math.cos(oFPData.get_T()) - oFPData.get_K() * this._GP.get_Y() * Math.sin(oFPData.get_T())); this._Y = (oFPData.get_Y() + oFPData.get_K() * this._GP.get_X() * Math.sin(oFPData.get_T()) + oFPData.get_K() * this._GP.get_Y() * Math.cos(oFPData.get_T())); return Boolean.valueOf(true); } public Boolean FunAntiCover(double x, double y) { Boolean bRtn = Boolean.valueOf(true); switch (this._lcs) { case BeiJingCJ: bRtn = Boolean.valueOf(BeiJintCJToWGS84(x, y)); break; default: bRtn = Boolean.valueOf(false); } return bRtn; } private boolean BeiJintCJToWGS84(double x, double y) { boolean bRtn = true; LocalCoordinateSys LCS = new BeiJingCJ(); FPData oFPData = LCS.getFPData(false, 117); this._X = (oFPData.get_X() + oFPData.get_K() * x * Math.cos(oFPData.get_T()) - oFPData.get_K() * y * Math.sin(oFPData.get_T())); this._Y = (oFPData.get_Y() + oFPData.get_K() * x * Math.sin(oFPData.get_T()) + oFPData.get_K() * y * Math.cos(oFPData.get_T())); if (!this._GP.AntiProjection(this._X, this._Y, 117).booleanValue()) { this._ErrMsg = ("高斯投影失敗:" + this._GP.get_ErrMsg()); bRtn = false; return bRtn; } if ((this._GP.get_L() < 1.5D) && (this._GP.get_L() > -1.5D)) { this._L = (117.0D + this._GP.get_L()); bRtn = true; } else if (this._GP.get_L() > 1.5D) { this._B = this._GP.get_Lat(); this._L = (117.0D + this._GP.get_L()); this._ErrMsg = "超出投影範圍,可能不準確"; bRtn = false; } else { FPData oFPData2 = LCS.getFPData(false, 114); this._X = (oFPData2.get_X() + oFPData2.get_K() * x * Math.cos(oFPData2.get_T()) - oFPData2.get_K() * y * Math.sin(oFPData2.get_T())); this._Y = (oFPData2.get_Y() + oFPData2.get_K() * x * Math.sin(oFPData2.get_T()) + oFPData2.get_K() * y * Math.cos(oFPData2.get_T())); if (!this._GP.AntiProjection(this._X, this._Y, 114).booleanValue()) { this._ErrMsg = ("高斯投影失敗:" + this._GP.get_ErrMsg()); bRtn = false; } this._L = (114.0D + this._GP.get_L()); bRtn = true; } this._B = this._GP.get_Lat(); return bRtn; } public double get_X() { return this._X; } public double get_Y() { return this._Y; } public double get_B() { return this._B; } public double get_L() { return this._L; } public String get_ErrMsg() { return this._ErrMsg; } }
GaussProjection.java
package PkgCover; public class GaussProjection { double f = 0.0D; double e2 = 0.0D; double e1 = 0.0D; double b; double a = 0.0D; private String _ErrMsg; private int _ZoneWide; private double _l; private int _Maridian; private double _Lng; private double _Lat; private double _Y; private double _X; private double _A8; private double _A6; private double _A4; private double _A2; private double _A0; private double _M8; private double _M6; private double _M4; private double _M2; private double _M0; public GaussProjection(enumEllipseSys ellipse, int zoneWide) { this._ZoneWide = zoneWide; switch (ellipse) { case WGS84: this.a = 6378245.0D; this.b = 6356863.0187730473D; this.e1 = (Math.sqrt(Math.pow(this.a, 2.0D) - Math.pow(this.b, 2.0D)) / this.a); this.e2 = (Math.sqrt(Math.pow(this.a, 2.0D) - Math.pow(this.b, 2.0D)) / this.b); break; case BeiJing54: this.a = 6378137.0D; this.b = 6356752.3141999999D; this.e1 = (Math.sqrt(Math.pow(this.a, 2.0D) - Math.pow(this.b, 2.0D)) / this.a); this.e2 = (Math.sqrt(Math.pow(this.a, 2.0D) - Math.pow(this.b, 2.0D)) / this.b); break; case XiAn80: this.a = 6378140.0D; this.b = 6356755.2881575283D; this.e1 = (Math.sqrt(Math.pow(this.a, 2.0D) - Math.pow(this.b, 2.0D)) / this.a); this.e2 = (Math.sqrt(Math.pow(this.a, 2.0D) - Math.pow(this.b, 2.0D)) / this.b); break; } this.f = ((this.a - this.b) / this.a); CalMidPara(); } public Boolean Projection(double B, double L, double H) { Boolean bRtn = Boolean.valueOf(true); try { int n = 0; if (this._ZoneWide == 6) { n = (int)L / 6; if (L % 6.0D > 0.0D) { n++; } this._Maridian = (6 * n - 3); this._l = (L - this._Maridian); } if (3 == this._ZoneWide) { n = (int)(L - 1.5D) / 3; if ((L - 1.5D) % 3.0D > 0.0D) { n++; } this._Maridian = (3 * n); this._l = (L - this._Maridian); } B = B * 3.141592653589793D / 180.0D; L = L * 3.141592653589793D / 180.0D; this._l = (this._l * 3.141592653589793D / 180.0D); double X = this._A0 * B - this._A2 * Math.sin(2.0D * B) / 2.0D + this._A4 * Math.sin(4.0D * B) / 4.0D - this._A6 * Math.sin(6.0D * B) / 6.0D + this._A8 * Math.sin(8.0D * B) / 8.0D; double T = Math.tan(B); double ita = this.e2 * Math.cos(B); double SinB = Math.sin(B); double CosB = Math.cos(B); double N = this.a * Math.pow(1.0D - Math.pow(this.e1 * SinB, 2.0D), -0.5D); this._X = (X + N * T * Math.pow(CosB, 2.0D) * Math.pow(this._l, 2.0D) / 2.0D + N * T * (5.0D - Math.pow(T, 2.0D) + 9.0D * Math.pow(ita, 2.0D) + 4.0D * Math.pow(ita, 2.0D)) * Math.pow(CosB * this._l, 4.0D) / 24.0D + N * T * (61.0D - 58.0D * Math.pow(T, 2.0D) + Math.pow(T, 4.0D)) * Math.pow(CosB * this._l, 6.0D) / 720.0D); this._Y = (N * CosB * this._l + N * (1.0D - Math.pow(T, 2.0D) + Math.pow(ita, 2.0D)) * Math.pow(CosB * this._l, 3.0D) / 6.0D + N * (5.0D - 18.0D * Math.pow(T, 2.0D) + Math.pow(T, 4.0D) + 14.0D * Math.pow(ita, 2.0D) - 58.0D * Math.pow(ita * T, 2.0D)) * Math.pow(CosB * this._l, 5.0D) / 120.0D); } catch (Exception ex) { this._ErrMsg = ex.getMessage(); bRtn = Boolean.valueOf(false); } return bRtn; } public Boolean AntiProjection(double x, double y, int maridian) { this._Maridian = maridian; boolean bRtn = true; try { double Bf0 = x / this._A0; double Bf = GetBf(Bf0, x); double Nf = this.a * Math.pow(1.0D - Math.pow(this.e1 * Math.sin(Bf), 2.0D), -0.5D); double Z = y / (Nf * Math.cos(Bf)); double Mf = this.a * (1.0D - this.e1 * this.e1) * Math.pow(1.0D - Math.pow(this.e1 * Math.sin(Bf), 2.0D), -1.5D); double Tf = Math.tan(Bf); double ITAf2 = Math.pow(this.e2 * Math.cos(Bf), 2.0D); double B2 = Tf * Math.pow(y, 2.0D) / (2.0D * Mf * Nf); double B4 = Tf * Math.pow(y, 4.0D) * (5.0D + 3.0D * Math.pow(Tf, 2.0D) + ITAf2 - 9.0D * Math.pow(Tf, 2.0D) * ITAf2) / (24.0D * Mf * Math.pow(Nf, 3.0D)); double B6 = Tf * Math.pow(y, 6.0D) * (61.0D + 90.0D * Math.pow(Tf, 2.0D) + 45.0D * Math.pow(Tf, 4.0D)) / (720.0D * Mf * Math.pow(Nf, 5.0D)); double B3 = (1.0D + 2.0D * Math.pow(Tf, 2.0D) + ITAf2) * Math.pow(y, 3.0D) / (6.0D * Math.pow(Nf, 3.0D) * Math.cos(Bf)); double B5 = (5.0D + 28.0D * Math.pow(Tf, 2.0D) + 24.0D * Math.pow(Tf, 4.0D) + 6.0D * ITAf2 + 8.0D * ITAf2) * Math.pow(y, 5.0D) / (120.0D * Math.pow(Nf, 5.0D) * Math.cos(Bf)); this._Lat = ((Bf - B2 + B4 - B6) * 180.0D / 3.141592653589793D); this._l = ((Z - B3 + B5) * 180.0D / 3.141592653589793D); } catch (Exception ex) { this._ErrMsg = (this._ErrMsg + "高斯投影反算出錯!" + ex.getMessage()); bRtn = false; } return Boolean.valueOf(bRtn); } private double GetBf(double bf, double x) { double M = -this._A2 * Math.sin(2.0D * bf) / 2.0D + this._A4 * Math.sin(4.0D * bf) / 4.0D - this._A6 * Math.sin(6.0D * bf) / 6.0D + this._A8 * Math.sin(8.0D * this.f) / 8.0D; double Bf = (x - M) / this._A0; if (Math.abs(bf - Bf) > 3.141592653589793D * Math.pow(10.0D, -8.0D) / 648.0D) { Bf = GetBf(Bf, x); } return Bf; } private void CalMidPara() { this._M0 = (this.a * (1.0D - Math.pow(this.e1, 2.0D))); this._M2 = (3.0D * Math.pow(this.e1, 2.0D) * this._M0 / 2.0D); this._M4 = (5.0D * Math.pow(this.e1, 2.0D) * this._M2 / 4.0D); this._M6 = (7.0D * Math.pow(this.e1, 2.0D) * this._M4 / 6.0D); this._M8 = (9.0D * Math.pow(this.e1, 2.0D) * this._M6 / 8.0D); this._A0 = (this._M0 + this._M2 / 2.0D + 3.0D * this._M4 / 8.0D + 5.0D * this._M6 / 16.0D + 35.0D * this._M8 / 128.0D); this._A2 = (this._M2 / 2.0D + this._M4 / 2.0D + 15.0D * this._M6 / 32.0D + 7.0D * this._M8 / 16.0D); this._A4 = (this._M4 / 8.0D + this._M6 * 3.0D / 16.0D + this._M8 * 7.0D / 32.0D); this._A6 = (this._M6 / 32.0D + this._M8 / 16.0D); this._A8 = (this._M8 / 128.0D); } public double get_X() { return this._X; } public double get_Y() { return this._Y; } public double get_Lat() { return this._Lat; } public double get_Lng() { return this._Lng; } public String get_ErrMsg() { return this._ErrMsg; } public double get_L() { return this._l; } public int get_Maridian() { return this._Maridian; } }
案例
首先經緯度轉換Util,把相應的城建座標"499549.528", "317657.996"轉換為經緯度
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; import PkgCover.CoodinateCover; import PkgCover.Coordinate; import PkgCover.CoordinateSys; import PkgCover.enumEllipseSys; import PkgCover.enumLocalCoordinateSys; public class Utils { public static Double[] getCoordinate(String coordx, String coordy) { Double[] returnCoordinate = new Double[2]; if (coordx == null || coordy == null) { return null; } CoodinateCover cc = new CoodinateCover(3, enumEllipseSys.WGS84, enumLocalCoordinateSys.BeiJingCJ); if (!cc.FunCover(Double.valueOf(coordy).doubleValue(), Double.valueOf(coordx).doubleValue())) { try { throw new RuntimeException(cc.get_ErrMsg()); } catch (Exception e) { System.out.println("捕獲轉換異常:" + e); } } returnCoordinate[0] = cc.get_Y(); returnCoordinate[1] = cc.get_X(); return returnCoordinate; } public static Double[] getAinCoordinate(String coordx, String coordy) { Double[] returnCoordinate = new Double[2]; if (coordx == null || coordy == null) { return null; } CoodinateCover cc = new CoodinateCover(3, enumEllipseSys.WGS84, enumLocalCoordinateSys.BeiJingCJ); if (!cc.FunAntiCover(Double.valueOf(coordy).doubleValue(), Double.valueOf(coordx).doubleValue())) { try { throw new RuntimeException(cc.get_ErrMsg()); } catch (Exception e) { System.out.println("捕獲轉換異常:" + e); } } if (cc.get_L() != 0.0D && cc.get_B() != 0.0D) { Coordinate _Coordinate = new Coordinate(cc.get_B(), cc.get_L(), CoordinateSys.WGS84); if (_Coordinate.WGS84ToGCJ02()) { returnCoordinate[0] = _Coordinate.get_GCJLat(); returnCoordinate[1] = _Coordinate.get_GCJLng(); } else { returnCoordinate[0] = cc.get_L(); returnCoordinate[1] = cc.get_B(); } } else { returnCoordinate[0] = cc.get_L(); returnCoordinate[1] = cc.get_B(); } return returnCoordinate; } public static void main(String[] args) { Double[] dd = Utils.getAinCoordinate("499549.528", "317657.996"); System.out.println(dd[0] + "," + dd[1]); } }