java 坐标转换工具类(很全面哦!wgs84.... gcj02(即火星坐标).... )

 今天给大家分享一个java实现的地图坐标系经纬度转换工具类

/*
 * Copyright (c). All rights reserved.
 * Use is subject to license terms.
 */
package com.sf.gis.boot.utils;

import org.apache.commons.codec.binary.Base64;

import java.io.*;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.DecimalFormat;

/**
 * 坐标转换工具(移植)。
 *
 * @author fanhuigang
 */
public class CoordTransform2
{
    private final static DecimalFormat FORMAT = new DecimalFormat("0.00000000");
    private final static int SCALE = 8;
    private final static double AVG_X = 0.006401062;
    private final static double AVG_Y = 0.0060424805;
    private final static double EARTH_RADIUS = 6378137.0;
    private final static double MARS_R = 6378245.0;
    private final static double MARS_EE = 0.00669342162296594323;
    
    /**
     * 预定义转换模式。
     */
    public static enum Schema
    {
        bdmc2g("bmc2g"), bdmc2gm("bmc2gm"), bdmc2bll("bmc2bll"), bll2bdmc("bll2bmc"), 
        g2bdmc("g2bmc"), gm2bdmc("gm2bmc"), /*gps2g("gps2g"), g2gps("g2gps"), */
        gps2b("gps2b"), b2gps("b2gps"), b2g("b2g"), g2b("g2b"), d2m("d2m"), m2d("m2d"),
        gps2mars("gps2mars"), mars2gps("mars2gps"), ll2wmc("ll2wmc"), wmc2ll("wmc2ll");
        
        private final String value;
        
        Schema(String value)
        {
            this.value = value;
        }

        public String getValue()
        {
            return value;
        }
    }

    /**
     * 变形后转变形前(高德坐标转GPS)
     *
     * @param lng
     * @param lat
     * @return
     */
   /* public static Double[] convertGoogle2GPS(double lng, double lat)
    {
        String url = String.format(SysConf.get().getString("transform.itf.url"),
                "Public2Secret", FORMAT.format(lng), FORMAT.format(lat), "3600");
        return getXYBy(url);
    }*/

    /**
     * 变形前转变形后(GPS转高德)
     *
     * @param lng
     * @param lat
     * @return
     */
  /*  public static Double[] convertGPS2Google(double lng, double lat)
    {
        String url = String.format(SysConf.get().getString("transform.itf.url"),
                "Secret2Public", FORMAT.format(lng), FORMAT.format(lat), "3600");
        return getXYBy(url);
    }
*/
    /**
     * 百度转高德(内网工具)
     *
     * @param lng
     * @param lat
     * @return
     */
    public static Double[] convertBaidu2Google(double lng, double lat)
    {
        String url = "http://10.2.10.51:81/cgi-bin/bd.fcgi/?opt=bd_decrypt&x=" + FORMAT.format(
                lng) + "&y=" + FORMAT.format(lat);
        return getXYBy(url);
    }

    /**
     * 高德转百度(内网工具)
     *
     * @param lng
     * @param lat
     * @return
     */
    public static Double[] convertGoogle2Baidu(double lng, double lat)
    {
        String urlstr = "http://10.2.10.51:81/cgi-bin/bd.fcgi/?opt=bd_encrypt&x=" + FORMAT.format(
                lng) + "&y=" + FORMAT.format(lat);
        return getXYBy(urlstr);
    }

    private static Double[] getXYBy(String urlstr)
    {
        Double[] xy = null;
        String result = readURLData(urlstr);
        if(result != null && result.length() > 5)
        {
            xy = readJSONBy(result);
        }
        return xy;
    }

    /**
     * GPS坐标转换为百度坐标
     *
     * @param lng
     * @param lat
     * @return
     */
    public static Double[] convertGPS2Baidu(double lng, double lat)
    {
        String url = "http://map.baidu.com/ag/coord/convert?from=0&to=4&x=" + FORMAT.format(
                lng) + "&y=" + FORMAT.format(lat);
        return getXY(url);
    }

    /**
     * 百度坐标转换为GPS坐标
     *
     * @param lng
     * @param lat
     * @return
     */
    public static Double[] convertBaidu2GPS(double lng, double lat)
    {
        return convertBaidu2GPS(lng, lat, 3);
    }

    public static Double[] convertBaidu2GPS(double lng, double lat, int c)
    {
        Double[] xy = new Double[2];
        if(c < 1)
        {
            return xy;
        }
        double ax = AVG_X;
        double ay = AVG_Y;
        for(int i = 1; i <= c; i++)
        {
            xy = convertBaidu2GPS(lng, lat, ax, ay);
            ax = lng - xy[0];
            ay = lat - xy[1];
        }
        return xy;
    }

    private static Double[] convertBaidu2GPS(double x, double y, double ax,
            double ay)
    {
        Double[] xy = null;
        double x_b = x - ax;
        double y_b = y - ay;
        Double[] xy_b = convertGPS2Baidu(x_b, y_b);
        if(xy_b != null)
        {
            xy = new Double[2];
            xy[0] = BigDecimal.valueOf(x + x_b - xy_b[0]).setScale(SCALE,
                    BigDecimal.ROUND_HALF_UP).doubleValue();
            xy[1] = BigDecimal.valueOf(y + y_b - xy_b[1]).setScale(SCALE,
                    BigDecimal.ROUND_HALF_UP).doubleValue();
        }
        return xy;
    }

    private static Double[] getXY(String urlstr)
    {
        Double[] xy = null;
        String result = readURLData(urlstr);
        if(result != null && result.length() > 5)
        {
            xy = readJSON(result);
        }
        return xy;
    }

    private static String readURLData(String urlstr)
    {
        String result = null;
        InputStream in = null;
        BufferedReader reader = null;
        FileOutputStream out = null;
        try
        {
            URL url = new URL(urlstr);
            HttpURLConnection httpConn = null;
            HttpURLConnection.setFollowRedirects(false);
            httpConn = (HttpURLConnection) url.openConnection();
            httpConn.setRequestMethod("GET");
            httpConn.setRequestProperty("Host", url.getHost());
            httpConn.setRequestProperty("User-Agent",
                    "Mozilla/5.0 (Windows NT 5.1; rv:11.0) Gecko/20100101 Firefox/11.0");
            httpConn.setRequestProperty("Accept",
                    "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
            httpConn.setRequestProperty("Accept-Language", "zh-cn");
            httpConn.setRequestProperty("Accept-Encoding", "deflate");
            httpConn.setRequestProperty("Connection", "keep-alive");
            httpConn.setConnectTimeout(20000);
            int responseCode = httpConn.getResponseCode();
            if(responseCode == 200)
            {
                in = httpConn.getInputStream();
                reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
                String line = null;
                StringBuffer sb = new StringBuffer();
                while((line = reader.readLine()) != null)
                {
                    sb.append(line);
                }
                result = sb.toString();
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                if(reader != null)
                {
                    reader.close();
                }
            }
            catch(IOException ex)
            {
            }
            try
            {
                if(in != null)
                {
                    in.close();
                }
            }
            catch(IOException ex)
            {
            }
            try
            {
                if(out != null)
                {
                    out.close();
                }
            }
            catch(IOException ex)
            {
                ex.printStackTrace();
            }
        }
        return result;
    }
    
    private static Double[] readJSONBy(String str)
    {
        Double[] xy = null;
        try
        {
            String value = str.substring(1, str.length() - 1);
            value = value.replace("\"", "");
            String[] results = value.split(",");
            if(results.length == 2)
            {
                String mapX = results[0].split(":")[1];
                String mapY = results[1].split(":")[1];
                xy = new Double[2];
                xy[0] = Double.parseDouble(mapX);
                xy[1] = Double.parseDouble(mapY);
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        return xy;
    }

    private static Double[] readJSON(String str)
    {
        Double[] xy = null;
        try
        {
            String value = str.substring(1, str.length() - 1);
            String[] results = value.split("\\,");
            if(results.length == 3)
            {
                if(results[0].split("\\:")[1].equals("0"))
                {
                    String mapX = results[1].split("\\:")[1];
                    String mapY = results[2].split("\\:")[1];
                    mapX = mapX.substring(1, mapX.length() - 1);
                    mapY = mapY.substring(1, mapY.length() - 1);
                    mapX = new String(Base64.decodeBase64(mapX));
                    mapY = new String(Base64.decodeBase64(mapY));
                    xy = new Double[2];
                    xy[0] = new BigDecimal(mapX).setScale(SCALE,
                            BigDecimal.ROUND_HALF_UP).doubleValue();
                    xy[1] = new BigDecimal(mapY).setScale(SCALE,
                            BigDecimal.ROUND_HALF_UP).doubleValue();
                }
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        return xy;
    }
    
    /**
     * 转换GPS坐标到MARS坐标。
     * @param x x坐标4gps
     * @param y y坐标4gps
     * @return mars坐标xy
     */
    public static Double[] convertGPS2MXY(double x, double y)
    {
        Double[] mxy = new Double[2];
        if(outOfChina(x, y))
        {
            mxy[0] = x;
            mxy[1] = y;
            return mxy;
        }
        double dLat = convertGPS2MY(x - 105.0, y - 35.0);
        double dLon = convertGPS2MX(x - 105.0, y - 35.0);
        double radLat = y / 180.0 * Math.PI;
        double magic = Math.sin(radLat);
        magic = 1 - MARS_EE * magic * magic;
        double sqrtMagic = Math.sqrt(magic);
        dLat = (dLat * 180.0) / ((MARS_R * (1 - MARS_EE)) / (magic * sqrtMagic) * Math.PI);
        dLon = (dLon * 180.0) / (MARS_R / sqrtMagic * Math.cos(radLat) * Math.PI);
        mxy[0] = x + dLon;
        mxy[1] = y + dLat;
        return mxy;
    }
    
    /**
     * 转换MARS坐标到GPS坐标。
     * @param x x坐标4mxy
     * @param y y坐标4mxy
     * @return gps坐标xy
     */
    public static Double[] convertMXY2GPS(double x, double y)
    {
        Double[] mxy = new Double[2];
        if(outOfChina(x, y))
        {
            mxy[0] = x;
            mxy[1] = y;
            return mxy;
        }
        double dLat = convertGPS2MY(x - 105.0, y - 35.0);
        double dLon = convertGPS2MX(x - 105.0, y - 35.0);
        double radLat = y / 180.0 * Math.PI;
        double magic = Math.sin(radLat);
        magic = 1 - MARS_EE * magic * magic;
        double sqrtMagic = Math.sqrt(magic);
        dLat = (dLat * 180.0) / ((MARS_R * (1 - MARS_EE)) / (magic * sqrtMagic) * Math.PI);
        dLon = (dLon * 180.0) / (MARS_R / sqrtMagic * Math.cos(radLat) * Math.PI);
        mxy[0] = x * 2 - (x + dLon);
        mxy[1] = y * 2 - (y + dLat);
        return mxy;
    }
    
    /**
     * 检查china边界。
     * @param x x坐标4gps
     * @param y y坐标4gps
     * @return 检查结果
     */
    private static boolean outOfChina(double x, double y)
    {  
        if(x < 72.004 || x > 137.8347)  
            return true;  
        if(y < 0.8293 || y > 55.8271)  
            return true;  
        return false;  
    }
    
    /**
     * 转换GPS坐标到MARS坐标4X。
     * @param x x坐标4gps
     * @param y y坐标4gps
     * @return x坐标4mars
     */
    private static double convertGPS2MY(double x, double y)
    {
        double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
        ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(y * Math.PI) + 40.0 * Math.sin(y / 3.0 * Math.PI)) * 2.0 / 3.0;
        ret += (160.0 * Math.sin(y / 12.0 * Math.PI) + 320 * Math.sin(y * Math.PI / 30.0)) * 2.0 / 3.0;
        return ret;
    }

    /**
     * 转换GPS坐标到MARS坐标4Y。
     * @param x x坐标4gps
     * @param y y坐标4gps
     * @return y坐标4mars
     */
    private static double convertGPS2MX(double x, double y)
    {
        double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
        ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(x * Math.PI) + 40.0 * Math.sin(x / 3.0 * Math.PI)) * 2.0 / 3.0;
        ret += (150.0 * Math.sin(x / 12.0 * Math.PI) + 300.0 * Math.sin(x / 30.0 * Math.PI)) * 2.0 / 3.0;
        return ret;
    }

    /**
     * 获得半径偏移量
     *
     * 以3000为周期的变化*0.00002
     *
     * @param y 纬度
     * @return 半径偏移量
     */
    private static double get_delta_r(double y)
    {
        return Math.sin(y * 3000 * (Math.PI / 180)) * 0.00002;
    }

    /**
     * 获得角度偏移量 以3000为周期的变化*0.000003
     *
     * @param x 经度
     * @return 角度偏移量
     */
    private static double get_delta_t(double x)
    {
        double d = Math.cos(x * 3000 * (Math.PI / 180)) * 0.000003;
        return d;
    }

    /**
     * 高德转百度(工具)
     *
     * @param lng
     * @param lat
     * @return
     */
    public static Double[] convertG2B(double lng, double lat)
    {
        // 确保以度参与计算
        lng = (Math.abs(lng) > 180d) ? lng / 3600d : lng;
        lat = (Math.abs(lat) > 180d) ? lat / 3600d : lat;
        double x1 = Math.cos(get_delta_t(lng) + Math.atan2(lat, lng)) * (get_delta_r(
                lat) + Math.sqrt(lng * lng + lat * lat)) + 0.0065;
        double y1 = Math.sin(get_delta_t(lng) + Math.atan2(lat, lng)) * (get_delta_r(
                lat) + Math.sqrt(lng * lng + lat * lat)) + 0.006;
        Double[] xys = new Double[2];
        xys[0] = BigDecimal.valueOf(x1).setScale(SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
        xys[1] = BigDecimal.valueOf(y1).setScale(SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
        return xys;
    }

    /**
     * 百度转高德(工具)默认迭代2次
     *
     * @param lng
     * @param lat
     * @return
     */
    public static Double[] convertB2G(double lng, double lat)
    {
        return convertB2G(lng, lat, 2);
    }

    /**
     * 百度转高德(工具)
     *
     * @param lng
     * @param lat
     * @param c 迭代次数
     * @return
     */
    public static Double[] convertB2G(double lng, double lat, int c)
    {
        // 确保以度参与计算
        lng = (Math.abs(lng) > 180d) ? lng / 3600d : lng;
        lat = (Math.abs(lat) > 180d) ? lat / 3600d : lat;
        Double[] xy = new Double[2];
        if(c < 1)
        {
            return xy;
        }
        double ax = AVG_X;
        double ay = AVG_Y;
        for(int i = 1; i <= c; i++)
        {
            xy = convertB2G(lng, lat, ax, ay);
            ax = lng - xy[0];
            ay = lat - xy[1];
        }
        return xy;
    }

    private static Double[] convertB2G(double x, double y, double ax, double ay)
    {
        // 确保以度参与计算
        x = (Math.abs(x) > 180d) ? x / 3600d : x;
        y = (Math.abs(y) > 180d) ? y / 3600d : y;
        Double[] xy = null;
        double x_b = x - ax;
        double y_b = y - ay;
        Double[] xy_b = convertG2B(x_b, y_b);
        if(xy_b != null)
        {
            xy = new Double[2];
            xy[0] = BigDecimal.valueOf(x + x_b - xy_b[0]).setScale(SCALE,
                    BigDecimal.ROUND_HALF_UP).doubleValue();
            xy[1] = BigDecimal.valueOf(y + y_b - xy_b[1]).setScale(SCALE,
                    BigDecimal.ROUND_HALF_UP).doubleValue();
        }
        return xy;
    }

    /**
     * 平面坐标转经纬度
     *
     * @param x 平面坐标X
     * @param y 平面坐标Y
     * @return
     */
    public static Double[] convertMC2Lnglat(double x, double y)
    {
        Double[] res = convertMC2LL(x, y);
        return new Double[]
        {
            new BigDecimal(res[0]).setScale(SCALE, BigDecimal.ROUND_HALF_UP).doubleValue(), new BigDecimal(
            res[1]).setScale(SCALE, BigDecimal.ROUND_HALF_UP).doubleValue()
        };
    }

    /**
     * 经纬度转平面坐标
     *
     * @param lng 经度
     * @param lat 纬度
     * @return
     */
    public static Double[] convertLnglat2MC(double lng, double lat)
    {
        Double[] res = convertLL2MC(lng, lat);
        return new Double[]
        {
            Double.parseDouble(String.format("%.2f", res[0])), Double.parseDouble(
            String.format("%.2f", res[1]))
        };
    }
    
    /**
     * 转换bdmc坐标到g经纬度坐标。
     * @param x mcx
     * @param y mcy
     * @return 转换后的g经纬度坐标
     */
    public static Double[] convertBMC2G(double x, double y)
    {
        Double[] xy = convertMC2Lnglat(x, y);
        return convertB2G(xy[0], xy[1]);
    }
    
    /**
     * 转换g经纬度坐标到bmc坐标。
     * @param x mcx
     * @param y mcy
     * @return 转换后的bmc坐标
     */
    public static Double[] convertG2BMC(double x, double y)
    {
        Double[] xy = convertG2B(x, y);
        return convertLL2MC(xy[0], xy[1]);
    }

    private static Double[] convertLL2MC(double x, double y)
    {
        // 确保以度参与计算
        x = (Math.abs(x) > 180d) ? x / 3600d : x;
        y = (Math.abs(y) > 180d) ? y / 3600d : y;
        double[] cD = null;
        double[] llband =
        {
            75, 60, 45, 30, 15, 0
        };
        double[][] ll2mc =
        {
            {
                -0.0015702102444, 111320.7020616939, 1704480524535203.0, -10338987376042340.0, 26112667856603880.0, -35149669176653700.0, 26595700718403920.0, -10725012454188240.0, 1800819912950474.0, 82.5
            },
            {
                0.0008277824516172526, 111320.7020463578, 647795574.6671607, -4082003173.641316, 10774905663.51142, -15171875531.51559, 12053065338.62167, -5124939663.577472, 913311935.9512032, 67.5
            },
            {
                0.00337398766765, 111320.7020202162, 4481351.045890365, -23393751.19931662, 79682215.47186455, -115964993.2797253, 97236711.15602145, -43661946.33752821, 8477230.501135234, 52.5
            },
            {
                0.00220636496208, 111320.7020209128, 51751.86112841131, 3796837.749470245, 992013.7397791013, -1221952.21711287, 1340652.697009075, -620943.6990984312, 144416.9293806241, 37.5
            },
            {
                -0.0003441963504368392, 111320.7020576856, 278.2353980772752, 2485758.690035394, 6070.750963243378, 54821.18345352118, 9540.606633304236, -2710.55326746645, 1405.483844121726, 22.5
            },
            {
                -0.0003218135878613132, 111320.7020701615, 0.00369383431289, 823725.6402795718, 0.46104986909093, 2351.343141331292, 1.58060784298199, 8.77738589078284, 0.37238884252424, 7.45
            }
        };
        x = getLoop(x, -180, 180);
        y = getRange(y, -74, 74);
        for(int cC = 0; cC < llband.length; cC++)
        {
            if(y >= llband[cC])
            {
                cD = ll2mc[cC];
                break;
            }
        }
        if(cD != null && cD.length > 0)
        {
            for(int cC = llband.length - 1; cC >= 0; cC--)
            {
                if(y <= -llband[cC])
                {
                    cD = ll2mc[cC];
                    break;
                }
            }
        }
        return convertor(x, y, cD);
    }

    private static Double[] convertor(double x, double y, double[] cD)
    {
        double t = cD[0] + cD[1] * Math.abs(x);
        double cB = Math.abs(y) / cD[9];
        double cE = cD[2] + cD[3] * cB + cD[4] * cB * cB + cD[5] * cB * cB * cB + cD[6] * cB * cB * cB * cB + cD[7] * cB * cB * cB * cB * cB + cD[8] * cB * cB * cB * cB * cB * cB;
        t *= (x < 0 ? -1 : 1);
        cE *= (y < 0 ? -1 : 1);
        return new Double[]
        {
            t, cE
        };
    }

    private static Double[] convertMC2LL(double x, double y)
    {
        double[] mcband =
        {
            12890594.86, 8362377.87, 5591021, 3481989.83, 1678043.12, 0
        };
        double[][] mc2ll =
        {
            {
                1.410526172116255e-8, 0.00000898305509648872, -1.9939833816331, 200.9824383106796, -187.2403703815547, 91.6087516669843, -23.38765649603339, 2.57121317296198, -0.03801003308653, 17337981.2
            },
            {
                -7.435856389565537e-9, 0.000008983055097726239, -0.78625201886289, 96.32687599759846, -1.85204757529826, -59.36935905485877, 47.40033549296737, -16.50741931063887, 2.28786674699375, 10260144.86
            },
            {
                -3.030883460898826e-8, 0.00000898305509983578, 0.30071316287616, 59.74293618442277, 7.357984074871, -25.38371002664745, 13.45380521110908, -3.29883767235584, 0.32710905363475, 6856817.37
            },
            {
                -1.981981304930552e-8, 0.000008983055099779535, 0.03278182852591, 40.31678527705744, 0.65659298677277, -4.44255534477492, 0.85341911805263, 0.12923347998204, -0.04625736007561, 4482777.06
            },
            {
                3.09191371068437e-9, 0.000008983055096812155, 0.00006995724062, 23.10934304144901, -0.00023663490511, -0.6321817810242, -0.00663494467273, 0.03430082397953, -0.00466043876332, 2555164.4
            },
            {
                2.890871144776878e-9, 0.000008983055095805407, -3.068298e-8, 7.47137025468032, -0.00000353937994, -0.02145144861037, -0.00001234426596, 0.00010322952773, -0.00000323890364, 826088.5
            }
        };
        double[] cE = new double[2];
        for(int i = 0; i < mcband.length; i++)
        {
            if(Math.abs(y) >= mcband[i])
            {
                cE = mc2ll[i];
                break;
            }
        }
        return convertor(x, y, cE);
    }

    private static double getRange(double cC, double a, double b)
    {
        cC = Math.max(cC, a);
        cC = Math.min(cC, b);
        return cC;
    }

    private static double getLoop(double cC, double a, double b)
    {
        while(cC > b)
        {
            cC -= b - a;
        }
        while(cC < a)
        {
            cC += b - a;
        }
        return cC;
    }

    /**
     * 获取图片左下角右上角经纬度
     *
     * @param x 图片x坐标
     * @param y 图片y坐标
     * @param level 级别
     * @return 116.361753,40.042802|116.362903,40.041918
     */
    public static Double[] getLnglat(int x, int y, int level)
    {
        Double[] xy1 = convertMC2Lnglat((2 << (25 - level)) * x,
                (2 << (25 - level)) * y);
        Double[] xy2 = convertMC2Lnglat((2 << (25 - level)) * (x + 1),
                (2 << (25 - level)) * (y + 1));
        return new Double[]
        {
            xy1[0], xy1[1], xy2[0], xy2[1]
        };
    }

    public static Integer[] getGridXYByXY(int minX, int maxX, int minY, int maxY,
            int levelSmall, int levelBig)
    {
        int c = 1 << (levelBig - levelSmall);
        return new Integer[]
        {
            minX * c, ((maxX + 1) * c - 1), minY * c, ((maxY + 1) * c - 1)
        };
    }

    public static Integer[] getGridXYByXY(int x, int y, int levelSmall,
            int levelBig)
    {
        return getGridXYByXY(x, x, y, y, levelSmall, levelBig);
    }

    /**
     * 通过经纬度获取图片左下角右上角经纬度范围
     *
     * @param lng_min 左下角经度
     * @param lat_min 左下角纬度
     * @param lng_max 右上角经度
     * @param lat_max 右上角纬度
     * @param level 级别
     * @return
     */
    public static Integer[] getGridXYByLnglat(double lng_min, double lat_min,
            double lng_max, double lat_max, int level)
    {
        Double[] pXY0 = convertLnglat2MC(Math.min(lng_min, lng_max),
                Math.min(lat_min, lat_max));
        Double[] pXY1 = convertLnglat2MC(Math.max(lng_min, lng_max),
                Math.max(lat_min, lat_max));
        int x0 = (int) Math.floor(pXY0[0] / (2 << (25 - level)));
        int y0 = (int) Math.floor(pXY0[1] / (2 << (25 - level)));
        int x1 = (int) Math.floor(pXY1[0] / (2 << (25 - level)));
        int y1 = (int) Math.floor(pXY1[1] / (2 << (25 - level)));
        return new Integer[]
        {
            x0, x1, y0, y1
        };
    }

    /**
     * 通过经纬度获取图片左下角右上角经纬度范围
     *
     * @param lng_min 左下角经度
     * @param lat_min 左下角纬度
     * @param lng_max 右上角经度
     * @param lat_max 右上角纬度
     * @param levelSmall 小级别(13)
     * @param levelBig 大级别(19)
     * @return
     */
    public static Integer[] getGridXYByLnglat(double lng_min, double lat_min,
            double lng_max, double lat_max, int levelSmall, int levelBig)
    {
        Integer[] g = getGridXYByLnglat(lng_min, lat_min, lng_max, lat_max,
                levelSmall);
        return getGridXYByXY(g[0], g[1], g[2], g[3], levelSmall, levelBig);
    }
    
    private static double getRad(double d)
    {
        return d * Math.PI / 180.0;
    }

    /**
     * 算法1:求两点之间的距离,输入单位: 度;返回单位:米。
     * @param lng1
     * @param lat1
     * @param lng2
     * @param lat2
     * @return 两点之间的距离
     */
    public static double getGreatCircleDistance(double lng1, double lat1,
            double lng2, double lat2)
    {
        // 确保以度参与计算
        lng1 = (Math.abs(lng1) > 180d) ? lng1 / 3600d : lng1;
        lat1 = (Math.abs(lat1) > 180d) ? lat1 / 3600d : lat1;
        lng2 = (Math.abs(lng2) > 180d) ? lng2 / 3600d : lng2;
        lat2 = (Math.abs(lat2) > 180d) ? lat2 / 3600d : lat2;
        double radLat1 = getRad(lat1);
        double radLat2 = getRad(lat2);

        double dy = radLat1 - radLat2;//a
        double dx = getRad(lng1) - getRad(lng2);//b

        double s = 2 * Math.asin(Math.sqrt(
                Math.pow(Math.sin(dy / 2), 2) + Math.cos(radLat1) * Math.cos(
                        radLat2) * Math.pow(Math.sin(dx / 2), 2)));
        s = s * EARTH_RADIUS;
        s = Math.round(s * 10000) / 10000.0;
        return s;
    }
    
    /**
     * 3857-->经纬度.
     * @param x
     * @param y
     * @return 经纬度坐标
     */
    public static Double[] inverseMercator(double x, double y)
    {
        double lon = x / 20037508.34d * 180.0d;
        double lat = y / 20037508.34d * 180.0d;
        lat = 180d / Math.PI * (2 * Math.atan(Math.exp(lat * Math.PI / 180d)) - Math.PI / 2);
        return new Double[] { lon, lat };
    }
    
    /**
     * 经纬度-->3857.
     * @param lon
     * @param lat
     * @return 3857坐标
     */
    public static Double[] forwardMercator(double lon, double lat)
    {
        double x = lon * 20037508.34d /180d;
        double y = Math.log(Math.tan((90 + lat) * Math.PI / 360)) / (Math.PI / 180);  
        y = y * 20037508.34d / 180d;
        return new Double [] { x, y };
    }
    
    /**
     * 度转秒。
     * @param x 经度(度)
     * @param y 维度(度)
     * @return 经纬度(秒)
     */
    private static Double[] convertD2M(double x, double y)
    {
        Double[] xy = new Double[2];
        xy[0] = (Math.abs(x) <= 180d) ? x * 3600 : x;
        xy[1] = (Math.abs(y) <= 180d) ? y * 3600 : y;
        return xy;
    }
    
    /**
     * 秒转度。
     * @param x 经度(秒)
     * @param y 维度(秒)
     * @return 经纬度(度)
     */
    private static Double[] convertM2D(double x, double y)
    {
        Double[] xy = new Double[2];
        xy[0] = (Math.abs(x) > 180d) ? x / 3600d : x;
        xy[1] = (Math.abs(y) > 180d) ? y / 3600d : y;
        return xy;
    }
    
    /**
     * 批量转换mc为g经纬度。
     * @param xyArray 逗号分隔的mc坐标串
     * @return 转换后的坐标串
     */
    public static String convertMC2GLnglat(String xyArray)
    {
        String xys[] = xyArray.split(",");
        StringBuilder sbd = new StringBuilder();
        for(int i = 0; i < xys.length; i += 2)
        {
            Double xy1[] = convertMC2Lnglat(Double.valueOf(xys[i]), Double.valueOf(xys[i + 1]));
            Double xy2[] = convertB2G(xy1[0].doubleValue(), xy1[1].doubleValue());
            sbd.append(String.format("%f,%f", xy2[0] * 3600D, xy2[1] * 3600D));
            if(i < xys.length - 2)
            {
                sbd.append(",");
            }
        }
        return sbd.toString();
    }
    
    /**
     * 批量按照目标schema转换坐标。
     * @param s 目标schema
     * @param xyArray 逗号分隔的坐标串
     * @return 转换后的坐标串
     */
    public static String convertSchema(Schema s, String xyArray)
    {
        String xys[] = xyArray.split(",");
        StringBuilder sbd = new StringBuilder();
        for(int i = 0; i < xys.length; i += 2)
        {
            Double[] xy = convertSchema(s, Double.valueOf(xys[i]), Double.valueOf(xys[i + 1]));
            sbd.append(String.format("%f,%f", xy[0], xy[1]));
            if(i < xys.length - 2)
            {
                sbd.append(",");
            }
        }
        return sbd.toString();
    }
    
    /**
     * 按照目标schema转换坐标。
     * @param s 目标schema
     * @param x 原始x
     * @param y 原始y
     * @return 转换后坐标
     */
    public static Double[] convertSchema(Schema s, double x, double y)
    {
        switch(s)
        {
            case bdmc2bll:
                return convertMC2Lnglat(x, y);
            case bll2bdmc:
                return convertLnglat2MC(x, y);
            case bdmc2g:
                return convertBMC2G(x, y);
            case bdmc2gm:
                Double[] xy = convertBMC2G(x, y);
                xy[0] *= (Math.abs(xy[0]) <= 180d) ? 3600 : 1;
                xy[1] *= (Math.abs(xy[1]) <= 180d) ? 3600 : 1;
                return xy;
            case g2bdmc:
            case gm2bdmc:
                return convertG2BMC(x, y);
          //  case gps2g:
          //      return convertGPS2Google(x, y);
           // case g2gps:
             //   return convertGoogle2GPS(x, y);
            case gps2b:
                return convertGPS2Baidu(x, y);
            case b2gps:
                return convertBaidu2GPS(x, y);
            case b2g:
                return convertB2G(x, y);
            case g2b:
                return convertG2B(x, y);
            case d2m:
                return convertD2M(x, y);
            case m2d:
                return convertM2D(x, y);
            case gps2mars://wgs84坐标转gcj02 加密
                return convertGPS2MXY(x, y);
            case mars2gps://gcj02转wgs84 解密
            	return convertMXY2GPS(x, y);
            case ll2wmc:
                return forwardMercator(x, y);
            case wmc2ll:
                return inverseMercator(x, y);
        }
        return null;
    }
}

例如我们查询到了一些地图上面的设备,需要把设备的wgs84经纬度转换成火星坐标,可以这样操作:

 /**
     * 讲设备的坐标按照目标schema转换坐标。
     *
     * @param detailVo
     * @return
     */
    private DeviceDetailVo convertXYSchema(DeviceDetailVo detailVo) {
        Double[] xyArray = CoordTransform2.convertSchema
                (CoordTransform2.Schema.gps2mars, detailVo.getX().doubleValue(), detailVo.getY().doubleValue());
        detailVo.setX(xyArray[0].floatValue());
        detailVo.setY(xyArray[1].floatValue());
        return detailVo;
    }

猜你喜欢

转载自blog.csdn.net/qq_31905135/article/details/107817307