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