1. 程式人生 > >城建座標與經緯度轉換工具

城建座標與經緯度轉換工具

核心部分底層原始碼

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]);
	}
}