mgrscoordconverter.java

来自「world wind java sdk 源码」· Java 代码 · 共 1,161 行 · 第 1/3 页

JAVA
1,161
字号
/*
Copyright (C) 2001, 2008 United States Government
as represented by the Administrator of the
National Aeronautics and Space Administration.
All Rights Reserved.
*/
package gov.nasa.worldwind.geom.coords;

import gov.nasa.worldwind.globes.Globe;
import gov.nasa.worldwind.geom.Angle;

/**
 * Converter used to translate MGRS coordinate strings to and from geodetic latitude and longitude.
 *
 * @author Patrick Murris
 * @version $Id: MGRSCoordConverter.java 10332 2009-04-19 02:19:39Z patrickmurris $
 * @see MGRSCoord
 */

/**
 * Ported to Java from the NGA GeoTrans mgrs.c and mgrs.h code. Contains routines to convert
 * from Geodetic to MGRS and the other direction.
 *
 * @author Garrett Headley, Patrick Murris
 */
class MGRSCoordConverter
{
    public static final int MGRS_NO_ERROR = 0;
    private static final int MGRS_LAT_ERROR = 0x0001;
    private static final int MGRS_LON_ERROR = 0x0002;
    public static final int MGRS_STRING_ERROR = 0x0004;
    private static final int MGRS_PRECISION_ERROR = 0x0008;
    private static final int MGRS_A_ERROR = 0x0010;
    private static final int MGRS_INV_F_ERROR = 0x0020;
    private static final int MGRS_EASTING_ERROR = 0x0040;
    private static final int MGRS_NORTHING_ERROR = 0x0080;
    private static final int MGRS_ZONE_ERROR = 0x0100;
    private static final int MGRS_HEMISPHERE_ERROR = 0x0200;
    private static final int MGRS_LAT_WARNING = 0x0400;
    private static final int MGRS_NOZONE_WARNING = 0x0800;
    private static final int MGRS_UTM_ERROR = 0x1000;
    private static final int MGRS_UPS_ERROR = 0x2000;

    private static final double PI = 3.14159265358979323;
    private static final double PI_OVER_2 = (PI / 2.0e0);
    private static final int MAX_PRECISION = 5;
    private static final double MIN_UTM_LAT = (-80 * PI) / 180.0;    // -80 degrees in radians
    private static final double MAX_UTM_LAT = (84 * PI) / 180.0;     // 84 degrees in radians
    public static final double DEG_TO_RAD = 0.017453292519943295;   // PI/180
    private static final double RAD_TO_DEG = 57.29577951308232087;   // 180/PI

    private static final double MIN_EAST_NORTH = 0;
    private static final double MAX_EAST_NORTH = 4000000;
    private static final double TWOMIL = 2000000;
    private static final double ONEHT = 100000;

    private static final String CLARKE_1866 = "CC";
    private static final String CLARKE_1880 = "CD";
    private static final String BESSEL_1841 = "BR";
    private static final String BESSEL_1841_NAMIBIA = "BN";

    // Ellipsoid parameters, default to WGS 84
    private  double MGRS_a = 6378137.0;          // Semi-major axis of ellipsoid in meters
    private  double MGRS_f = 1 / 298.257223563;  // Flattening of ellipsoid
    private  double MGRS_recpf = 298.257223563;
    private  String MGRS_Ellipsoid_Code = "WE";

    private Globe globe;
    private  String MGRSString = "";
    private  long ltr2_low_value;
    private  long ltr2_high_value;       // this is only used for doing MGRS to xxx conversions.
    private  double false_northing;
    private  long lastLetter;
    private  long last_error = MGRS_NO_ERROR;
    private  double north, south, min_northing;
    private  double latitude;
    private  double longitude;

    private static final  int LETTER_A = 0;   /* ARRAY INDEX FOR LETTER A               */
    private static final  int LETTER_B = 1;   /* ARRAY INDEX FOR LETTER B               */
    private static final  int LETTER_C = 2;   /* ARRAY INDEX FOR LETTER C               */
    private static final  int LETTER_D = 3;   /* ARRAY INDEX FOR LETTER D               */
    private static final  int LETTER_E = 4;   /* ARRAY INDEX FOR LETTER E               */
    private static final  int LETTER_F = 5;   /* ARRAY INDEX FOR LETTER E               */
    private static final  int LETTER_G = 6;   /* ARRAY INDEX FOR LETTER H               */
    private static final  int LETTER_H = 7;   /* ARRAY INDEX FOR LETTER H               */
    private static final  int LETTER_I = 8;   /* ARRAY INDEX FOR LETTER I               */
    private static final  int LETTER_J = 9;   /* ARRAY INDEX FOR LETTER J               */
    private static final  int LETTER_K = 10;   /* ARRAY INDEX FOR LETTER J               */
    private static final  int LETTER_L = 11;   /* ARRAY INDEX FOR LETTER L               */
    private static final  int LETTER_M = 12;   /* ARRAY INDEX FOR LETTER M               */
    private static final  int LETTER_N = 13;   /* ARRAY INDEX FOR LETTER N               */
    private static final  int LETTER_O = 14;   /* ARRAY INDEX FOR LETTER O               */
    private static final  int LETTER_P = 15;   /* ARRAY INDEX FOR LETTER P               */
    private static final  int LETTER_Q = 16;   /* ARRAY INDEX FOR LETTER Q               */
    private static final  int LETTER_R = 17;   /* ARRAY INDEX FOR LETTER R               */
    private static final  int LETTER_S = 18;   /* ARRAY INDEX FOR LETTER S               */
    private static final  int LETTER_T = 19;   /* ARRAY INDEX FOR LETTER S               */
    private static final  int LETTER_U = 20;   /* ARRAY INDEX FOR LETTER U               */
    private static final  int LETTER_V = 21;   /* ARRAY INDEX FOR LETTER V               */
    private static final  int LETTER_W = 22;   /* ARRAY INDEX FOR LETTER W               */
    private static final  int LETTER_X = 23;   /* ARRAY INDEX FOR LETTER X               */
    private static final  int LETTER_Y = 24;   /* ARRAY INDEX FOR LETTER Y               */
    private static final  int LETTER_Z = 25;   /* ARRAY INDEX FOR LETTER Z               */
    private static final  int MGRS_LETTERS = 3;  /* NUMBER OF LETTERS IN MGRS              */

    private static final String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";


    // UPS Constants are in the following order:
    //    long letter;            /* letter representing latitude band      */
    //    long ltr2_low_value;    /* 2nd letter range - high number         */
    //    long ltr2_high_value;   /* 2nd letter range - low number          */
    //    long ltr3_high_value;   /* 3rd letter range - high number (UPS)   */
    //    double false_easting;   /* False easting based on 2nd letter      */
    //    double false_northing;  /* False northing based on 3rd letter     */
    private static final  long[][] upsConstants = {
            {LETTER_A, LETTER_J, LETTER_Z, LETTER_Z, 800000, 800000},
            {LETTER_B, LETTER_A, LETTER_R, LETTER_Z, 2000000, 800000},
            {LETTER_Y, LETTER_J, LETTER_Z, LETTER_P, 800000, 1300000},
            {LETTER_Z, LETTER_A, LETTER_J, LETTER_P, 2000000, 1300000}};

    // Latitude Band Constants are in the following order:
    //        long letter;            /* letter representing latitude band  */
    //        double min_northing;    /* minimum northing for latitude band */
    //        double north;           /* upper latitude for latitude band   */
    //        double south;           /* lower latitude for latitude band   */
    private static final  double[][] latitudeBandConstants = {
            {LETTER_C, 1100000.0, -72.0, -80.5},
            {LETTER_D, 2000000.0, -64.0, -72.0},
            {LETTER_E, 2800000.0, -56.0, -64.0},
            {LETTER_F, 3700000.0, -48.0, -56.0},
            {LETTER_G, 4600000.0, -40.0, -48.0},
            {LETTER_H, 5500000.0, -32.0, -40.0},
            {LETTER_J, 6400000.0, -24.0, -32.0},
            {LETTER_K, 7300000.0, -16.0, -24.0},
            {LETTER_L, 8200000.0, -8.0, -16.0},
            {LETTER_M, 9100000.0, 0.0, -8.0},
            {LETTER_N, 0.0, 8.0, 0.0},
            {LETTER_P, 800000.0, 16.0, 8.0},
            {LETTER_Q, 1700000.0, 24.0, 16.0},
            {LETTER_R, 2600000.0, 32.0, 24.0},
            {LETTER_S, 3500000.0, 40.0, 32.0},
            {LETTER_T, 4400000.0, 48.0, 40.0},
            {LETTER_U, 5300000.0, 56.0, 48.0},
            {LETTER_V, 6200000.0, 64.0, 56.0},
            {LETTER_W, 7000000.0, 72.0, 64.0},
            {LETTER_X, 7900000.0, 84.5, 72.0}};

    private  class MGRSComponents
    {
        private final int zone;
        private final int latitudeBand;
        private final int squareLetter1;
        private final int squareLetter2;
        private final double easting;
        private final double northing;
        private final int precision;

        public MGRSComponents(int zone, int latitudeBand, int squareLetter1, int squareLetter2,
                              double easting, double northing, int precision)
        {
            this.zone = zone;
            this.latitudeBand = latitudeBand;
            this.squareLetter1 = squareLetter1;
            this.squareLetter2 = squareLetter2;
            this.easting = easting;
            this.northing = northing;
            this.precision = precision;
        }

        public String toString()
        {
            return "MGRS: " + zone + " " +
                    alphabet.charAt(latitudeBand) + " " +
                    alphabet.charAt(squareLetter1) + alphabet.charAt(squareLetter2) + " " +
                    easting + " " +
                    northing + " " +
                    "(" + precision + ")";
        }
    }

    MGRSCoordConverter(Globe globe)
    {
        this.globe = globe;
        if(globe != null)
        {
            double a = globe.getEquatorialRadius();
            double f = (globe.getEquatorialRadius() - globe.getPolarRadius()) / globe.getEquatorialRadius();
            setMGRSParameters(a, f, MGRS_Ellipsoid_Code);
        }
    }

    /**
     * The function setMGRSParameters receives the ellipsoid parameters and sets the corresponding state variables. If
     * any errors occur, the error code(s) are returned by the function, otherwise MGRS_NO_ERROR is returned.
     *
     * @param mgrs_a        Semi-major axis of ellipsoid in meters
     * @param mgrs_f        Flattening of ellipsoid
     * @param ellipsoidCode 2-letter code for ellipsoid
     * @return error code
     */
    public  long setMGRSParameters(double mgrs_a, double mgrs_f, String ellipsoidCode)
    {
        if (mgrs_a <= 0.0)
            return MGRS_A_ERROR;

        if (mgrs_f == 0.0)
            return MGRS_INV_F_ERROR;
        double inv_f = 1 / mgrs_f;
        if (inv_f < 250 || inv_f > 350)
            return MGRS_INV_F_ERROR;

        MGRS_a = mgrs_a;
        MGRS_f = mgrs_f;
        MGRS_Ellipsoid_Code = ellipsoidCode;

        return MGRS_NO_ERROR;
    }

    /**
     * @return Flattening of ellipsoid
     */
    public  double getMGRS_f()
    {
        return MGRS_f;
    }

    /**
     * @return Semi-major axis of ellipsoid in meters
     */
    public  double getMGRS_a()
    {
        return MGRS_a;
    }

    /**
     * @return Latitude band letter
     */
    private  long getLastLetter()
    {
        return lastLetter;
    }

    /**
     * @return 2-letter code for ellipsoid
     */
    public  String getMGRS_Ellipsoid_Code()
    {
        return MGRS_Ellipsoid_Code;
    }

    /**
     * The function ConvertMGRSToGeodetic converts an MGRS coordinate string
     * to Geodetic (latitude and longitude) coordinates
     * according to the current ellipsoid parameters.  If any errors occur,
     * the error code(s) are returned by the function, otherwise UTM_NO_ERROR
     * is returned.
     *
     * @param MGRSString MGRS coordinate string.
     * @return the error code.
     */
    public  long convertMGRSToGeodetic (String MGRSString)
    {
        latitude = 0;
        longitude = 0;
        long error_code = checkZone(MGRSString);
        if (error_code == MGRS_NO_ERROR)
        {
            UTMCoord UTM = convertMGRSToUTM (MGRSString);
            if(UTM != null)
            {
                latitude = UTM.getLatitude().radians;
                longitude = UTM.getLongitude().radians;
            }
            else
                error_code = MGRS_UTM_ERROR;
        }
        else if (error_code == MGRS_NOZONE_WARNING)
        {
            // TODO: polar conversion
            UPSCoord UPS = convertMGRSToUPS(MGRSString);
            if(UPS != null)
            {
                latitude = UPS.getLatitude().radians;
                longitude = UPS.getLongitude().radians;
            }
            else
                error_code = MGRS_UPS_ERROR;

        }
        return (error_code);
    }

    public  double getLatitude()
    {
        return latitude;
    }

    public  double getLongitude()
    {
        return longitude;
    }

    /**
     * The function Break_MGRS_String breaks down an MGRS
     * coordinate string into its component parts. Updates last_error.
     *
     * @param  MGRSString the MGRS coordinate string
     * @return the corresponding <code>MGRSComponents</code> or <code>null</code>.
     */
    private  MGRSComponents breakMGRSString (String MGRSString)
    {
        int num_digits;
        int num_letters;
        int i = 0;
        int j = 0;
        long error_code = MGRS_NO_ERROR;

        int zone = 0;
        int[] letters = new int[3];
        long easting = 0;
        long northing = 0;
        int precision = 0;

        while (i < MGRSString.length() && MGRSString.charAt(i) == ' ')
            i++;  /* skip any leading blanks */
        j = i;
        while (i < MGRSString.length() && Character.isDigit(MGRSString.charAt(i)))
            i++;
        num_digits = i - j;
        if (num_digits <= 2)
            if (num_digits > 0)
            {
                /* get zone */
                zone = Integer.parseInt(MGRSString.substring(j, i));
                if ((zone < 1) || (zone > 60))
                    error_code |= MGRS_STRING_ERROR;
            }
            else
                error_code |= MGRS_STRING_ERROR;
        j = i;

        while (i < MGRSString.length() && Character.isLetter(MGRSString.charAt(i)))
            i++;
        num_letters = i - j;
        if (num_letters == 3)
        {
            /* get letters */
            letters[0] = alphabet.indexOf(Character.toUpperCase(MGRSString.charAt(j)));
            if ((letters[0] == LETTER_I) || (letters[0] == LETTER_O))
                error_code |= MGRS_STRING_ERROR;
            letters[1] = alphabet.indexOf(Character.toUpperCase(MGRSString.charAt(j + 1)));
            if ((letters[1] == LETTER_I) || (letters[1] == LETTER_O))
                error_code |= MGRS_STRING_ERROR;
            letters[2] = alphabet.indexOf(Character.toUpperCase(MGRSString.charAt(j + 2)));
            if ((letters[2] == LETTER_I) || (letters[2] == LETTER_O))
                error_code |= MGRS_STRING_ERROR;
        }
        else
            error_code |= MGRS_STRING_ERROR;
        j = i;
        while (i < MGRSString.length() && Character.isDigit(MGRSString.charAt(i)))
            i++;
        num_digits = i - j;
        if ((num_digits <= 10) && (num_digits % 2 == 0))
        {
            /* get easting, northing and precision */
            int n;
            double multiplier;
            /* get easting & northing */
            n = num_digits / 2;
            precision = n;
            if (n > 0)
            {
                easting = Integer.parseInt(MGRSString.substring(j, j + n));
                northing = Integer.parseInt(MGRSString.substring(j + n, j + n + n));
                multiplier = Math.pow (10.0, 5 - n);
                easting *= multiplier;
                northing *= multiplier;
            }
            else
            {
                easting = 0;
                northing = 0;
            }
        }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?