package publicsWay; import java.text.DecimalFormat; public class XyToLatLngConverter { private static final DecimalFormat COORDINATE_FORMAT = new DecimalFormat("0.0000000"); /** * ½«¾Ö²¿×ø±êת»»Îª¾­Î³¶È×ø±ê * * @param localX ¾Ö²¿X×ø±ê(ÀåÃ×) * @param localY ¾Ö²¿Y×ø±ê(ÀåÃ×) * @param latA µãAµÄγ¶È(¶È·Ö¸ñʽ) * @param lonA µãAµÄ¾­¶È(¶È·Ö¸ñʽ) * @param latB µãBµÄγ¶È(¶È·Ö¸ñʽ) * @param lonB µãBµÄ¾­¶È(¶È·Ö¸ñʽ) * @param localXA µãAµÄ¾Ö²¿X×ø±ê(ÀåÃ×) * @param localYA µãAµÄ¾Ö²¿Y×ø±ê(ÀåÃ×) * @param localXB µãBµÄ¾Ö²¿X×ø±ê(ÀåÃ×) * @param localYB µãBµÄ¾Ö²¿Y×ø±ê(ÀåÃ×) * @return ×Ö·û´®Êý×é: * [0] Ê®½øÖƶÈγ¶È, * [1] Ê®½øÖƶȾ­¶È, * [2] ¶È·Ö¸ñʽγ¶È, * [3] ¶È·Ö¸ñʽ¾­¶È */ public static String[] convertLocalToGlobalCoordinates( String localX, String localY, double latA, double lonA, double latB, double lonB, double localXA, double localYA, double localXB, double localYB) { // 1. ¼ÆËã×ø±êϵת»»²ÎÊý double[] transformParams = CoordinateTranslator.computeTransformParamsWithTwoPoints( latA, lonA, latB, lonB, localXA, localYA, localXB, localYB); // 2. ½âÎöÊäÈë×ø±ê²¢×ª»»ÎªÃ× double x = Double.parseDouble(localX) / 100.0; double y = Double.parseDouble(localY) / 100.0; // 3. ´Óת»»²ÎÊýÖÐÌáÈ¡±ØÒªÐÅÏ¢ double originEasting = transformParams[0]; // Ô­µã¶«×ø±ê(Ã×) double originNorthing = transformParams[1]; // Ô­µã±±×ø±ê(Ã×) double cosTheta = transformParams[2]; // Ðýת¾ØÕócos·ÖÁ¿ double sinTheta = transformParams[3]; // Ðýת¾ØÕósin·ÖÁ¿ double zone = transformParams[5]; // UTM´øºÅ // 4. ½«¾Ö²¿×ø±êת»»ÎªUTM×ø±ê double[] utmCoordinates = convertLocalToUtm(x, y, originEasting, originNorthing, cosTheta, sinTheta); // 5. ½«UTM×ø±êת»»Îª¾­Î³¶È double[] latLng = convertUtmToWgs84(utmCoordinates[0], utmCoordinates[1], zone); // 6. ×¼±¸½á¹ûÊý×é String[] result = new String[4]; result[0] = COORDINATE_FORMAT.format(latLng[0]); // Ê®½øÖƶÈγ¶È result[1] = COORDINATE_FORMAT.format(latLng[1]); // Ê®½øÖƶȾ­¶È // 7. ת»»Îª¶È·Ö¸ñʽ double latDegMin = convertDecimalToDegMin(latLng[0]); double lngDegMin = convertDecimalToDegMin(latLng[1]); result[2] = COORDINATE_FORMAT.format(latDegMin); // ¶È·Ö¸ñʽγ¶È result[3] = COORDINATE_FORMAT.format(lngDegMin); // ¶È·Ö¸ñʽ¾­¶È return result; } /** * ½«Ê®½øÖƶÈת»»Îª¶È·Ö¸ñʽ * @param decimalDegrees Ê®½øÖƶÈ×ø±êÖµ * @return ¶È·Ö¸ñÊ½×ø±êÖµ (dddmm.mmmm) */ private static double convertDecimalToDegMin(double decimalDegrees) { double degrees = Math.floor(decimalDegrees); double minutes = (decimalDegrees - degrees) * 60.0; return degrees * 100.0 + minutes; } /** * ½«¾Ö²¿×ø±êת»»ÎªUTM×ø±ê * * @param localX ¾Ö²¿×ø±êϵXÖµ(Ã×) * @param localY ¾Ö²¿×ø±êϵYÖµ(Ã×) * @param originEasting Ô­µã¶«×ø±ê(Ã×) * @param originNorthing Ô­µã±±×ø±ê(Ã×) * @param cosTheta Ðýת¾ØÕócos·ÖÁ¿ * @param sinTheta Ðýת¾ØÕósin·ÖÁ¿ * @return UTM×ø±êÊý×é [¶«×ø±ê, ±±×ø±ê] */ private static double[] convertLocalToUtm( double localX, double localY, double originEasting, double originNorthing, double cosTheta, double sinTheta) { // ½»»»XY×ø±ê£¨¾Ö²¿×ø±êϵͨ³£ÒÔYΪǰ½ø·½Ïò£© double rotatedX = localY; double rotatedY = localX; // Ó¦ÓÃÐýתºÍÆ½ÒÆ±ä»» double dx = cosTheta * rotatedX + sinTheta * rotatedY; double dy = -sinTheta * rotatedX + cosTheta * rotatedY; return new double[] { dx + originEasting, // ¶«×ø±ê dy + originNorthing // ±±×ø±ê }; } /** * ½«UTM×ø±êת»»ÎªWGS84¾­Î³¶È * * @param easting UTM¶«×ø±ê(Ã×) * @param northing UTM±±×ø±ê(Ã×) * @param zone UTM´øºÅ * @return ¾­Î³¶ÈÊý×é [γ¶È, ¾­¶È] (Ê®½øÖƶÈ) */ public static double[] convertUtmToWgs84(double easting, double northing, double zone) { return utm2ll_wgs84(easting, northing, zone); } /** * UTM×ø±êתWGS84¾­Î³¶ÈʵÏÖ */ private static double[] utm2ll_wgs84(double x, double y, double f) { double[] latlon = new double[2]; double A1 = 6378137.0; double F1 = 298.257223563; // ³£Á¿¶¨Òå double D0 = 180 / Math.PI; double maxiter = 100; double eps = 1e-11; double K0 = 0.9996; double X0 = 500000; double Y0 = (f < 0) ? 1e7 : 0; double P0 = 0; double L0 = (6 * Math.abs(f) - 183) / D0; double E1 = Math.sqrt((A1 * A1 - (A1 * (1 - 1 / F1)) * (A1 * (1 - 1 / F1)))) / A1; double N = K0 * A1; double[] C = coef(E1, 0); double YS = Y0 - N * (C[0] * P0 + C[1] * Math.sin(2 * P0) + C[2] * Math.sin(4 * P0) + C[3] * Math.sin(6 * P0) + C[4] * Math.sin(8 * P0)); C = coef(E1, 1); double zta = (y - YS) / (N * C[0]); double ztb = (x - X0) / (N * C[0]); double L = zta; double LS = ztb; for (int i = 2; i < 6; i++) { double zta_temp = zta * (i - 1) * 2; double ztb_temp = ztb * (i - 1) * 2; L = L - C[i - 1] * Math.sin(zta_temp) * Math.cosh(ztb_temp); LS = LS - C[i - 1] * Math.cos(zta_temp) * Math.sinh(ztb_temp); } double l = L0 + Math.atan(Math.sinh(LS) / Math.cos(L)); double p = Math.asin(Math.sin(L) / Math.cosh(LS)); L = Math.log(Math.tan(Math.PI / 4 + p / 2)); p = 2 * Math.atan(Math.exp(L)) - Math.PI / 2; double p0 = 0; double n = 0; while ((p0 == 0 || Math.abs(p - p0) > eps) && n < maxiter) { p0 = p; double es = E1 * Math.sin(p0); p = 2 * Math.atan(Math.pow((1 + es) / (1 - es), E1 / 2) * Math.exp(L)) - Math.PI / 2; n = n + 1; } latlon[0] = p * D0; latlon[1] = l * D0; return latlon; } /** * ¼ÆËãUTMת»»ÏµÊý */ private static double[] coef(double e, int m) { double[][] c0; double[] c = new double[5]; if (m == 0) { c0 = new double[][] { {-175.0 / 16384.0, 0.0, -5 / 256.0, 0.0, -3 / 64.0, 0.0, -1 / 4.0, 0.0, 1.0}, {-105 / 4096.0, 0.0, -45 / 1024.0, 0.0, -3 / 32.0, 0.0, -3 / 8.0, 0.0, 0.0}, {525 / 16384.0, 0.0, 45 / 1024.0, 0.0, 15 / 256.0, 0.0, 0.0, 0.0, 0.0}, {-175 / 12288.0, 0.0, -35 / 3072.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {315 / 131072.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0} // 5x9 }; } else { c0 = new double[][] { {-175.0 / 16384.0, 0.0, -5 / 256.0, 0.0, -3 / 64.0, 0.0, -1 / 4.0, 0.0, 1.0}, {1 / 61440.0, 0.0, 7 / 2048.0, 0.0, 1 / 48.0, 0.0, 1 / 8.0, 0.0, 0.0}, {59 / 368640.0, 0.0, 3 / 1280.0, 0.0, 1 / 768.0, 0.0, 0.0, 0.0, 0.0}, {283 / 430080.0, 0.0, 17 / 30720.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4397 / 41287680.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0} // 5x9 }; } for (int i = 1; i <= 5; i++) { for (int j = 1; j <= 9; j++) { c[i - 1] += c0[i - 1][j - 1] * Math.pow(e, 9 - j); } } return c; } }