精华内容
下载资源
问答
  • 今天给大家分享一个java实现的地图坐标系经纬度转换工具类 /* * Copyright (c). All rights reserved. * Use is subject to license terms. */ package com.sf.gis.boot.utils; import org.apache.commons....

     今天给大家分享一个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;
        }
    

     

    展开全文
  • 自己写的一个java版图形化界面坐标转换工具,支持十进制坐标和度分秒坐标批量互转
  • 收集的java坐标转换工具,包括WGS84、GCJ02B、BD09,及国内纠偏。 收集的java坐标转换工具,包括WGS84、GCJ02B、BD09,及国内纠偏。
  • 百度地图坐标转换工具java后台代码,java后台处理坐标代码
  • 1. 主流坐标系简介 WGS84坐标系 地球坐标系,国际上通用的坐标系 使用GPS芯片或者北斗芯片的设备,获取的经纬度就是WGS84地理坐标系。 地图API:谷歌地图使用的是WGS84坐标系,但是中国范围使用的是GCJ02坐标系 ...

    1. 主流坐标系简介

    • WGS84坐标系

      地球坐标系,国际上通用的坐标系

      使用GPS芯片或者北斗芯片的设备,获取的经纬度就是WGS84地理坐标系。

      地图API:谷歌地图使用的是WGS84坐标系,但是中国范围使用的是GCJ02坐标系

    • GCJ02坐标系

      火星坐标系,WGS84坐标系经过加密后的坐标系

      出于国家安全考虑,国内的所有导航电子地图必须使用国家测绘局制定的加密坐标系,即将一个真实的经纬度通过加密变成一个对应位置不正确的经纬度

      地图API:高德MapABC地图、腾讯搜搜地图、阿里云地图

    • BD09坐标系

      百度坐标系,GCJ02加密后的坐标系

      地图API:百度地图

    2. 坐标转换工具类

    2.1 坐标实体类

    public class Point {
        private double lng;
        private double lat;
    
        public Point() {
        }
    
        public Point(double lng, double lat) {
            this.lng = lng;
            this.lat = lat;
        }
    
        public double getLng() {
            return lng;
        }
    
        public void setLng(double lng) {
            this.lng = lng;
        }
    
        public double getLat() {
            return lat;
        }
    
        public void setLat(double lat) {
            this.lat = lat;
        }
    
        @Override
        public String toString() {
            return "Point{" +
                    "lng=" + lng +
                    ", lat=" + lat +
                    '}';
        }
    }
    

    2.2 工具类

    public class CoordinateTransform {
        /**
         * 圆周率
         */
        private static final double PI = 3.1415926535897932384626D;
    
        /**
         * 火星坐标系与百度坐标系转换的中间量
         */
        private static final double X_PI = 3.14159265358979324 * 3000.0 / 180.0D;
    
        /**
         * 地球长半轴
         */
        private static final double SEMI_MAJOR = 6378245.0D;
    
        /**
         * 扁率
         * 计算方式: 长半轴 a,  1/f = 298.3
         * b = a * (1 - f)
         * 扁率 ae = (a^2 - b^2) / a^2
         */
        private static final double FLATTENING = 0.00669342162296594323D;
    
        /**
         * 中国的经纬度位置
         */
        private static final double LNG_E1 = 72.004;
        private static final double LNG_E2 = 137.8347;
        private static final double LAT_N1 = 0.8293;
        private static final double LAT_N2 = 55.8271;
    
        /**
         * WGS84 => GCJ02 地球坐标系 => 火星坐标系
         * @param lng
         * @param lat
         * @return
         */
        public static Point wgs84ToGcj02(double lng, double lat) {
            if (isInChina(lng, lat)) {
                return new Point(lng, lat);
            }
    
            double[] offset = offset(lng, lat);
            double mglng = lng + offset[0];
            double mglat = lat + offset[1];
    
            return new Point(mglng, mglat);
        }
    
        /**
         * GCJ02 => WGS84 火星坐标系 => 地球坐标系(有误差)
         * @param lng
         * @param lat
         * @return
         */
        public static Point gcj02ToWgs84(double lng, double lat) {
            if (isInChina(lng, lat)) {
                return new Point(lng, lat);
            }
    
            double[] offset = offset(lng, lat);
            double mglng = lng - offset[0];
            double mglat = lat - offset[1];
    
            return new Point(mglng, mglat);
        }
    
        /**
         * GCJ02 => WGS84 火星坐标系 => 地球坐标系(精确)
         * @param lng
         * @param lat
         * @return
         */
        public static Point gcj02ToWgs84Exactly(double lng, double lat) {
            if (isInChina(lng, lat)) {
                return new Point(lng, lat);
            }
    
            double initDelta = 0.01;
            double threshold = 0.000000001;
            double dLat = initDelta, dLon = initDelta;
            double mLat = lat - dLat, mLon = lng - dLon;
            double pLat = lat + dLat, pLon = lng + dLon;
            double wgsLat, wgsLng, i = 0;
            while (true) {
                wgsLat = (mLat + pLat) / 2;
                wgsLng = (mLon + pLon) / 2;
                Point point = wgs84ToGcj02(wgsLng, wgsLat);
                dLon = point.getLng() - lng;
                dLat = point.getLat() - lat;
                if ((Math.abs(dLat) < threshold) && (Math.abs(dLon) < threshold)) {
                    break;
                }
                if (dLat > 0) {
                    pLat = wgsLat;
                } else{
                    mLat = wgsLat;
                }
                if (dLon > 0) {
                    pLon = wgsLng;
                } else {
                    mLon = wgsLng;
                }
                if (++i > 10000) {
                    break;
                }
            }
    
            return new Point(wgsLng, wgsLat);
        }
    
        /**
         * GCJ02 => BD09 火星坐标系 => 百度坐标系
         * @param lng
         * @param lat
         * @return
         */
        public static Point gcj02ToBd09(double lng, double lat) {
            double z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * X_PI);
            double theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * X_PI);
            double bd_lng = z * Math.cos(theta) + 0.0065;
            double bd_lat = z * Math.sin(theta) + 0.006;
            return new Point(bd_lng, bd_lat);
        }
    
        /**
         * BD09 => GCJ02 百度坐标系 => 火星坐标系
         * @param lng
         * @param lat
         * @return
         */
        public static Point bd09ToGcj02(double lng, double lat) {
            double x = lng - 0.0065;
            double y = lat - 0.006;
            double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * X_PI);
            double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * X_PI);
            double gcj_lng = z * Math.cos(theta);
            double gcj_lat = z * Math.sin(theta);
            return new Point(gcj_lng, gcj_lat);
        }
    
        /**
         * WGS84 => BD09 地球坐标系 => 百度坐标系
         * @param lng
         * @param lat
         * @return
         */
        public static Point wgs84ToBd09(double lng, double lat) {
            Point point = wgs84ToGcj02(lng, lat);
            return gcj02ToBd09(point.getLng(), point.getLat());
        }
    
        /**
         * BD09 => WGS84 百度坐标系 => 地球坐标系
         * @param lng
         * @param lat
         * @return
         */
        public static Point bd09ToWgs84(double lng, double lat) {
            Point point = bd09ToGcj02(lng, lat);
            return gcj02ToWgs84(point.getLng(), point.getLat());
        }
    
        /**
         * 经纬度位于中国境外返回true,境内返回false
         * @param lng 	经度
         * @param lat	纬度
         * @return
         */
        public static boolean isInChina(double lng, double lat) {
            if (lng < LNG_E1 || lng > LNG_E2) {
                return true;
            }
            if (lat < LAT_N1 || lat > LAT_N2) {
                return true;
            }
            return false;
        }
    
        /**
         * 经度偏移量
         * @param lng
         * @param lat
         * @return
         */
        private static double transformLng(double lng, double lat) {
            double ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
            ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
            ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
            ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
            return ret;
        }
    
        /**
         * 纬度偏移量
         * @param lng
         * @param lat
         * @return
         */
        private static double transformLat(double lng, double lat) {
            double ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat
                    + 0.2 * Math.sqrt(Math.abs(lng));
            ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
            ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
            ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
            return ret;
        }
    
        /**
         * 偏移量
         * @param lng
         * @param lat
         * @return
         */
        public static double[] offset(double lng, double lat) {
            double[] lngLat = new double[2];
            double dlng = transformLng(lng - 105.0, lat - 35.0);
            double dlat = transformLat(lng - 105.0, lat - 35.0);
            double radlat = lat / 180.0 * PI;
            double magic = Math.sin(radlat);
            magic = 1 - FLATTENING * magic * magic;
            double sqrtMagic = Math.sqrt(magic);
            dlng = (dlng * 180.0) / (SEMI_MAJOR / sqrtMagic * Math.cos(radlat) * PI);
            dlat = (dlat * 180.0) / ((SEMI_MAJOR * (1 - FLATTENING)) / (magic * sqrtMagic) * PI);
            lngLat[0] = dlng;
            lngLat[1] = dlat;
            return lngLat;
        }
    }
    
    
    展开全文
  • @Test public void convertLatLonByCoordinate() { String newCoordinateType = "baidu"; String originalCoordinateType = "wgs84"; double lng = 115.25; double lat = 39.526128; logger.info("result:{}", ...
  • Kettle 压缩包,数据库驱动jar,坐标转换工具类jar,java代码
  • 七参数、四参数坐标转换工具
  • 坐标转换工具

    2018-11-29 09:31:19
    集合了各个坐标系之间的转换,以及计算坐标直接的距离等多个方法
  • 主要有三大功能:地理编码查询,坐标转换,POI查询,可以实现一般地理分析功能。ps:部分功能需注册
  • java geotools 坐标转换

    千次阅读 2020-08-08 20:15:30
    这里写自定义目录标题Java geotools 坐标转换坐标转换pom文件代码shp坐标系转换 Java geotools 坐标转换坐标转换 我点坐标转换为4326到3857,虽然我平时都是4546到3857,都一样。主要时因为我手里没有4546的...

    Java geotools 坐标转换

    点坐标转换

    我点坐标转换为4326到3857,虽然我平时都是4546到3857,都一样。主要时因为我手里没有4546的坐标,

    pom文件

    这个geotools的依赖比较“皮干”,要是下载不成功,就去官网geotools下的quickstart 的Mavenquick quickstart下面找仓库地址。

      <repositories>
          <repository>
            <id>osgeo</id>
            <name>OSGeo Release Repository</name>
            <url>https://repo.osgeo.org/repository/release/</url>
            <snapshots><enabled>false</enabled></snapshots>
            <releases><enabled>true</enabled></releases>
          </repository>
          <repository>
            <id>osgeo-snapshot</id>
            <name>OSGeo Snapshot Repository</name>
            <url>https://repo.osgeo.org/repository/snapshot/</url>
            <snapshots><enabled>true</enabled></snapshots>
            <releases><enabled>false</enabled></releases>
          </repository>
        </repositories>
         <dependency>
                <groupId>org.geotools</groupId>
                <artifactId>gt-epsg-hsql</artifactId>
                <version>20.0</version>
            </dependency>
    ```<dependency>
                <groupId>org.geotools</groupId>
                <artifactId>gt-referencing</artifactId>
                <version>20.0</version>
            </dependency>
            <dependency>
                <groupId>org.geotools</groupId>
                <artifactId>gt-api</artifactId>
                <version>20.0</version>
            </dependency>
    

    代码

    package com.wangkang.gts4vect;
    
    import org.geotools.geometry.jts.JTS;
    
    import org.geotools.referencing.CRS;
    import org.locationtech.jts.geom.Coordinate;
    
    import org.opengis.referencing.FactoryException;
    import org.opengis.referencing.crs.CoordinateReferenceSystem;
    import org.opengis.referencing.operation.MathTransform;
    
    import java.text.DecimalFormat;
    
    public class MyGeotools {
        public static void main(String[] args) {
    //        GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
    //        WKTReader reader = new WKTReader( geometryFactory );
            //某点的经纬度
            Double y = 34.26095856;
            Double x = 108.94237668;
            Double[] coordinate = getCoordinate(x, y);
            System.out.println(coordinate[0] + " " + coordinate[1]);
    
        }
    
        //坐标转换
        public static Double[] getCoordinate(Double x, Double y) {
            Double[] res = new Double[2];
            Coordinate tar = null;
            try {
                //封装点,这个是通用的,也可以用POINT(y,x)
                // private static WKTReader reader = new WKTReader( geometryFactory );
                Coordinate sour = new Coordinate(y, x);
                //这里要选择转换的坐标系是可以随意更换的
                CoordinateReferenceSystem source = CRS.decode("EPSG:4326");
                CoordinateReferenceSystem target = CRS.decode("EPSG:3857");
                //建立转换,下面两个我屏掉的转换方式会报出需要3/7参数的异常
                // MathTransform mathTransform = CRS.findMathTransform(source, target);
                //MathTransform mathTransform1 = CRS.findMathTransform(source, target, false);
                MathTransform transform = CRS.findMathTransform(source, target, true);
                tar = new Coordinate();
                //转换
                JTS.transform(sour, tar, transform);
            } catch (FactoryException | org.opengis.referencing.operation.TransformException e) {
                e.printStackTrace();
            }
            String[] split = (tar.toString().substring(1, tar.toString().length() - 1)).split(",");
            //经纬度精度
            DecimalFormat fm = new DecimalFormat("0.0000000");
            res[0] = Double.valueOf(fm.format(Double.valueOf(split[0])));
            res[1] = Double.valueOf(fm.format(Double.valueOf(split[1])));
            return res;
        }
    }
    
    

    结果如下
    在这里插入图片描述

    在这个转换类中,x,y 的位置调换了,这个是我们国家和国外的差异,约定成俗的东西,记住就好,为什么呢?因为不记住接下来的shp坐标系转换图像就飘了,飘到。。。。
    如果说整个科学技术不好看,好吧,我再换种写法

    package com.wangkang.gts4vect;
    
    import org.geotools.geometry.jts.JTS;
    import org.geotools.geometry.jts.JTSFactoryFinder;
    import org.geotools.referencing.CRS;
    import org.locationtech.jts.geom.Coordinate;
    import org.locationtech.jts.geom.Geometry;
    import org.locationtech.jts.geom.GeometryFactory;
    import org.locationtech.jts.io.ParseException;
    import org.locationtech.jts.io.WKTReader;
    import org.opengis.referencing.FactoryException;
    import org.opengis.referencing.crs.CoordinateReferenceSystem;
    import org.opengis.referencing.operation.MathTransform;
    import org.opengis.referencing.operation.TransformException;
    
    import java.text.DecimalFormat;
    
    public class MyGeotools2 {
        static  GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
        static  WKTReader reader = new WKTReader( geometryFactory );
        public static void main(String[] args) {
    
            //某点的经纬度
            Double y=34.26095856;
            Double x=108.94237668;
            try {
                //封装点,x,y 要反过来,不反过来就报纬度超过90的异常
                String point="POINT("+y+" "+x+")";
                Geometry geometry = reader.read(point);
                //这里要选择转换的坐标系是可以随意更换的
                CoordinateReferenceSystem source = CRS.decode("EPSG:4326");
                CoordinateReferenceSystem target = CRS.decode("EPSG:3857");
                //建立转换,下面两个我屏掉的转换方式会报出需要3/7参数的异常
                // MathTransform mathTransform = CRS.findMathTransform(source, target);
                //MathTransform mathTransform1 = CRS.findMathTransform(source, target, false);
                MathTransform transform = CRS.findMathTransform(source, target,true);
    
                //转换
                Geometry transform1 = JTS.transform(geometry, transform);
                System.out.println(transform1);
            } catch (FactoryException | TransformException | ParseException e) {
                e.printStackTrace();
            }
        }
    
    }
    
    

    结果如下
    在这里插入图片描述
    其实整个转化就两句代码
    MathTransform transform = CRS.findMathTransform(source, target,true);
    Geometry transform1 = JTS.transform(geometry, transform);
    就这两句。

    shp坐标系转换

    依赖自己整,上工具类

    package com.wangkang.gts4vect;
    
    import org.geotools.data.FeatureWriter;
    import org.geotools.data.FileDataStoreFactorySpi;
    import org.geotools.data.shapefile.ShapefileDataStore;
    import org.geotools.data.shapefile.ShapefileDataStoreFactory;
    import org.geotools.data.simple.SimpleFeatureIterator;
    import org.geotools.data.simple.SimpleFeatureSource;
    import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
    import org.geotools.geometry.jts.JTS;
    import org.geotools.geometry.jts.JTSFactoryFinder;
    import org.geotools.referencing.CRS;
    import org.locationtech.jts.geom.Geometry;
    import org.locationtech.jts.geom.GeometryFactory;
    import org.locationtech.jts.io.WKTReader;
    import org.opengis.feature.simple.SimpleFeature;
    import org.opengis.feature.simple.SimpleFeatureType;
    import org.opengis.referencing.crs.CoordinateReferenceSystem;
    import org.opengis.referencing.operation.MathTransform;
    import static org.geotools.data.Transaction.AUTO_COMMIT;
    
    import java.io.File;
    import java.io.Serializable;
    import java.util.HashMap;
    import java.util.Map;
    
    public class geotools3 {
       private static GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory( null );
       private static WKTReader reader = new WKTReader( geometryFactory );
       /**
        * 单个geom转换
        * geotools的安装包中的x,y坐标是反着的,因此,直接用geomtry转换,导出的数据是错误,先的将
        * x,y的坐标换过来。所以,我选择拼装geomtry。
        * @param geom
        * @return
        */
       public static Geometry lonlat2WebMactor(Geometry geom,String epsg){
    
           try{
               //CoordinateReferenceSystem的生成方法有两种,EPSG和WKT,然而,我发现把我需要的坐标系的prj文件中的内容用来转换会报“不存在。。。。什么这样的。。”
               //所以采用EPSG,即使使用了EPSG,导出的转换后的投影文件的prj仍然不对,arcgis 无法识别。当然,同一个坐标系下的prj 文件的内容是相同的,用别的替换即可。
               CoordinateReferenceSystem crsresource = CRS.decode("EPSG:"+epsg);
               CoordinateReferenceSystem crsTarget = CRS.decode("EPSG:3857");
               //CoordinateReferenceSystem crsTarget = CRS.decode(strWKTMercator);
               // 投影转换
               MathTransform transform = CRS.findMathTransform(crsresource, crsTarget,true);
               String geom1 = geom.toString();
               String[] split = geom1.substring(geom1.lastIndexOf("(")+1, geom1.length() - 3).split(",");
               StringBuffer res=new StringBuffer();
               res.append("MULTIPOLYGON (((");
               for(int i=0;i<split.length;i++){
    
                   int space = split[i].lastIndexOf(" ");
                   Double x=Double.valueOf(split[i].substring(0,space).trim());
                   Double y=Double.valueOf(split[i].substring(space).trim());
                   //使用coordinate时,产生的结果dest中的x坐标的位数是科学计数
    //                Coordinate source = new Coordinate(y, x);
    //                Coordinate dest = new Coordinate();
    //                JTS.transform(source,dest, transform);
    //                String[] str = dest.toString().substring(1, dest.toString().length() - 1).split(",");
                   String point="POINT("+y+" "+x+")";
                   Geometry pointGeom = reader.read(point);
                   Geometry resGeom = JTS.transform(pointGeom, transform);
                   String[] str = resGeom.toString().substring(resGeom.toString().lastIndexOf("(")+1, resGeom.toString().length() - 1).split("\\s+");
                   res.append(str[0]+" "+str[1]+",");
    
               }
               String result = res.substring(0, res.length() - 1);
               result=result+")))";
               Geometry read = reader.read(result);
    
    
               return read;
           }
           catch (Exception e) {
               e.printStackTrace();
               return null;
           }
       }
    
       /**
        * 坐标转换:WGS84转墨卡托
        * shp文件坐标转换。本质是每一个geom转换
        * @param inputShp shp输入路径
        * @param outputShp shp输出路径     * 
        * @param  epsg 输入文件的epsg
        */
       public void projectShape(String inputShp, String outputShp,String epsg){
           try {
               //源shape文件
               ShapefileDataStore shapeDS = (ShapefileDataStore) new ShapefileDataStoreFactory().createDataStore(new File(inputShp).toURI().toURL());
               //创建目标shape文件对象
               Map<String, Serializable> params = new HashMap<String, Serializable>();
               FileDataStoreFactorySpi factory = new ShapefileDataStoreFactory();
               params.put(ShapefileDataStoreFactory.URLP.key, new File(outputShp).toURI().toURL());
               ShapefileDataStore ds = (ShapefileDataStore) factory.createNewDataStore(params);
               // 设置属性
               SimpleFeatureSource fs = shapeDS.getFeatureSource(shapeDS.getTypeNames()[0]);
    
               //CoordinateReferenceSystem crs = CRS.parseWKT(strWKTMercator);
               CoordinateReferenceSystem crs = CRS.decode("EPSG:3857");
    
               ds.createSchema(SimpleFeatureTypeBuilder.retype(fs.getSchema(),crs));
               //设置writer
               FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(ds.getTypeNames()[0],AUTO_COMMIT);
               //写记录
               SimpleFeatureIterator it = fs.getFeatures().features();
    
               try {
                   while (it.hasNext()) {
                       SimpleFeature f = it.next();
                       SimpleFeature fNew = writer.next();
                       fNew.setAttributes(f.getAttributes());
                       //每个geom转换
                       Geometry geom = lonlat2WebMactor((Geometry)f.getAttribute("the_geom"),epsg);
                       fNew.setAttribute("the_geom", geom);
                   }
    
               }
               finally {
                   it.close();
               }
               writer.write();
               writer.close();
               ds.dispose();
               shapeDS.dispose();
           }
           catch (Exception e) {
               e.printStackTrace();
           }
       }
    
       public static void main(String[] args) {
          
       }
    
    }
    
    

    上面的只能转换面,写的也很蹩脚,令人痛心疾首,所以lonlat2WebMactor方法更新如下

       try{        
                CoordinateReferenceSystem crsresource = CRS.decode("EPSG:"+epsg);
                CoordinateReferenceSystem crsTarget = CRS.decode("EPSG:3857");
                // 投影转换
                MathTransform transform = CRS.findMathTransform(crsresource, crsTarget,true);
                Coordinate[] coordinates = geom.getCoordinates();
                for (Coordinate coordinate : coordinates) {               
                    double x = coordinate.getX();
                    coordinate.setX(coordinate.getY());
                    coordinate.setY(x);
                }
                Geometry transform1 = JTS.transform(geom, transform);
    
                return transform1;
            }
            catch (Exception e) {
                e.printStackTrace();
                return null;
            }
    

    转换的功能已经完成了。
    需要注意的是:
    1.转换完成后(我这里是3857),prj的文件内容是有问题的。arcgis,QGIS并不能识别这个空间坐标系
    如图:有问题的
    在这里插入图片描述
    用arcgis转换出的3857的prj是:

    String prj="PROJCS[\"WGS_1984_Web_Mercator_Auxiliary_Sphere\","
                + "GEOGCS[\"GCS_WGS_1984\","
                + "DATUM[\"D_WGS_1984\","
                + "SPHEROID[\"WGS_1984\",6378137.0,298.257223563]],"
                + "PRIMEM[\"Greenwich\",0.0],"
                + "UNIT[\"Degree\",0.0174532925199433]],"
                + "PROJECTION[\"Mercator_Auxiliary_Sphere\"],"
                + "PARAMETER[\"False_Easting\",0.0],"
                + "PARAMETER[\"False_Northing\",0.0],"
                + "PARAMETER[\"Central_Meridian\",0.0],"
                + "PARAMETER[\"Standard_Parallel_1\",0.0],"
                + "PARAMETER[\"Auxiliary_Sphere_Type\",0.0],"
                + "UNIT[\"Meter\",1.0]]";
    

    测试阶段,可以手动把prj的内容替换了。我用的时候写了一个扣JIO的东西。目的,替换prj中的内容

    package com.suntoon.util;
    
    
    import com.suntoon.mapper.CoordinateSystemMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import javax.annotation.Resource;
    import java.io.*;
    @Component
    public class PrjUtil {
        
    
        /**
         * 修改prj文件中的坐标系
         * path:prj文件的全路径
         */
        public void editPrj(String path){
                final String MKT84 = "PROJCS[\"WGS_1984_Web_Mercator_Auxiliary_Sphere\","
                + "GEOGCS[\"GCS_WGS_1984\","
                + "DATUM[\"D_WGS_1984\","
                + "SPHEROID[\"WGS_1984\",6378137.0,298.257223563]],"
                + "PRIMEM[\"Greenwich\",0.0],"
                + "UNIT[\"Degree\",0.0174532925199433]],"
                + "PROJECTION[\"Mercator_Auxiliary_Sphere\"],"
                + "PARAMETER[\"False_Easting\",0.0],"
                + "PARAMETER[\"False_Northing\",0.0],"
                + "PARAMETER[\"Central_Meridian\",0.0],"
                + "PARAMETER[\"Standard_Parallel_1\",0.0],"
                + "PARAMETER[\"Auxiliary_Sphere_Type\",0.0],"
                + "UNIT[\"Meter\",1.0]]";
            File file = new File(path);
            try (FileOutputStream outputStream = new FileOutputStream(file);
                  OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream,"utf-8");
                  BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
            ){
                bufferedWriter.write(MKT84);
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    
    
    }
    

    2.切记x,y是位置换了的,不然,有时候不会报错,改完prj的文件arcgis可以打开,但是,和用arcgis转出的图层的样子,属性内容是一样的,但是坐标不对(可以发布看下返回链接的bbox的经纬度,也可以几何计算看看)。
    3.我把用arcgis转换和用geotools转换的结果做了对比
    geotools:
    在这里插入图片描述
    arcgis:
    在这里插入图片描述
    但从边界看起来,似乎是有误差,而且误差不小。但是,坐标是一摸一样的。在显示的位数中,没有误差。后来放大图层,观看边界,发现图形是完全重合的。这个显示的问题并不会影响获取属性数据。

    展开全文
  • 本工具类为java版地图坐标转换工具类,适用于SuperMap、ArcGIS、MapInfo等主流的地图引擎
  • 批量转换工具类达到和百度、高德在线api一样精度,完全可以用于生产,经过验证的。 地图坐标转换(火星、谷歌、百度、腾讯、高德)以及主流坐标系介绍 美国GPS使用的是WGS84的坐标系统,以经纬度的形式来表示地球...

    💨 作者:laker,因为喜欢LOL滴神faker,又是NBA湖人队🏀(laker)粉丝儿(主要是老詹的粉丝儿),本人又姓,故取笔名:laker
    ❤️喜欢分享自己工作中遇到的问题和解决方案以及一些读书笔记和心得分享
    🌰本人创建了微信公众号【Java大厂面试官】,用于和大家交流分享
    🏰 个人微信【lakernote】,加作者备注下暗号:cv之道


    本文工具类,经过验证与各厂商百度、高德提供的在线转换精度基本一致,完全可以应用到生产环境

    前言

    美国GPS使用的是WGS84的坐标系统,以经纬度的形式来表示地球平面上的某一个位置,这应该是国际共识。但在我国,出于国家安全考虑国内所有导航电子地图必须使用国家测绘局制定的加密坐标系统,即将一个真实的经纬度坐标加密成一个不正确的经纬度坐标,我们在业内将前者称之为地球坐标,后者称之为火星坐标

    主流坐标系介绍

    现在互联网主要使用坐标系为以下三种:

    国际标准坐标 (WGS84)

    • 国际标准,从 GPS 设备中取出的数据的坐标系
    • 国际地图提供商使用的坐标系

    火星坐标 (GCJ-02)也叫国测局坐标系

    • 中国标准,从国行移动设备中定位获取的坐标数据使用这个坐标系
    • 国家规定: 国内出版的各种地图系统(包括电子形式),必须至少采用GCJ-02对地理位置进行首次加密。

    百度坐标 (BD-09)

    • 百度标准,百度 SDK,百度地图,Geocoding 使用
    • 在GCJ-02基础上二次加密而成

    从设备获取经纬度坐标

    • gps设备一般采用的是WGS84,经纬度格式转换工具CoordinateUtil
    • 如果使用的是百度sdk那么可以获得百度坐标(bd09)或者火星坐标(GCJ02),默认是bd09
    • 如果使用的是ios的原生定位库,那么获得的坐标是WGS84
    • 如果使用的是高德sdk,那么获取的坐标是GCJ02

    互联网在线地图使用的坐标系

    WGS84坐标系

    • 谷歌国外地图
    • osm地图等国外的地图

    火星坐标系

    • 高德地图
    • 腾讯地图
    • 谷歌国内地图

    百度坐标系

    • 百度地图

    转换方式

    方式优点缺点
    各官网在线api转换结果准确有各种api调用限制,例如:频率,次数等
    算法工具类无任何限制,想怎么用就怎么用可能找的算法或者工具类不准;所以我找了很久并测试到了一个,nice

    1. 各官网在线api

    • 高德地图

    https://lbs.amap.com/api/webservice/guide/api/convert

    • 百度地图

    https://lbsyun.baidu.com/index.php?title=webapi/guide/changeposition

    • 腾讯地图

    https://lbs.qq.com/service/webService/webServiceGuide/webServiceTranslate

    2. 算法工具类

    • 百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换的工具
    /**
     * 百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换的工具
     * 
     * @see 参考https://github.com/wandergis/coordtransform实现的Java版本
     * @author geosmart
     */
    public class CoordinateTransformUtil {
    	static double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
    	// π
    	static double pi = 3.1415926535897932384626;
    	// 长半轴
    	static double a = 6378245.0;
    	// 扁率
    	static double ee = 0.00669342162296594323;
    
    	/**
    	 * 百度坐标系(BD-09)转WGS坐标
    	 * 
    	 * @param lng 百度坐标纬度
    	 * @param lat 百度坐标经度
    	 * @return WGS84坐标数组
    	 */
    	public static double[] bd09towgs84(double lng, double lat) {
    		double[] gcj = bd09togcj02(lng, lat);
    		double[] wgs84 = gcj02towgs84(gcj[0], gcj[1]);
    		return wgs84;
    	}
    
    	/**
    	 * WGS坐标转百度坐标系(BD-09)
    	 * 
    	 * @param lng WGS84坐标系的经度
    	 * @param lat WGS84坐标系的纬度
    	 * @return 百度坐标数组
    	 */
    	public static double[] wgs84tobd09(double lng, double lat) {
    		double[] gcj = wgs84togcj02(lng, lat);
    		double[] bd09 = gcj02tobd09(gcj[0], gcj[1]);
    		return bd09;
    	}
    
    	/**
    	 * 火星坐标系(GCJ-02)转百度坐标系(BD-09)
    	 * 
    	 * @see 谷歌、高德——>百度
    	 * @param lng 火星坐标经度
    	 * @param lat 火星坐标纬度
    	 * @return 百度坐标数组
    	 */
    	public static double[] gcj02tobd09(double lng, double lat) {
    		double z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_pi);
    		double theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_pi);
    		double bd_lng = z * Math.cos(theta) + 0.0065;
    		double bd_lat = z * Math.sin(theta) + 0.006;
    		return new double[] { bd_lng, bd_lat };
    	}
    
    	/**
    	 * 百度坐标系(BD-09)转火星坐标系(GCJ-02)
    	 * 
    	 * @see 百度——>谷歌、高德
    	 * @param lng 百度坐标纬度
    	 * @param lat 百度坐标经度
    	 * @return 火星坐标数组
    	 */
    	public static double[] bd09togcj02(double bd_lon, double bd_lat) {
    		double x = bd_lon - 0.0065;
    		double y = bd_lat - 0.006;
    		double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
    		double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
    		double gg_lng = z * Math.cos(theta);
    		double gg_lat = z * Math.sin(theta);
    		return new double[] { gg_lng, gg_lat };
    	}
    
    	/**
    	 * WGS84转GCJ02(火星坐标系)
    	 * 
    	 * @param lng WGS84坐标系的经度
    	 * @param lat WGS84坐标系的纬度
    	 * @return 火星坐标数组
    	 */
    	public static double[] wgs84togcj02(double lng, double lat) {
    		if (out_of_china(lng, lat)) {
    			return new double[] { lng, lat };
    		}
    		double dlat = transformlat(lng - 105.0, lat - 35.0);
    		double dlng = transformlng(lng - 105.0, lat - 35.0);
    		double radlat = lat / 180.0 * pi;
    		double magic = Math.sin(radlat);
    		magic = 1 - ee * magic * magic;
    		double sqrtmagic = Math.sqrt(magic);
    		dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi);
    		dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * pi);
    		double mglat = lat + dlat;
    		double mglng = lng + dlng;
    		return new double[] { mglng, mglat };
    	}
    
    	/**
    	 * GCJ02(火星坐标系)转GPS84
    	 * 
    	 * @param lng 火星坐标系的经度
    	 * @param lat 火星坐标系纬度
    	 * @return WGS84坐标数组
    	 */
    	public static double[] gcj02towgs84(double lng, double lat) {
    		if (out_of_china(lng, lat)) {
    			return new double[] { lng, lat };
    		}
    		double dlat = transformlat(lng - 105.0, lat - 35.0);
    		double dlng = transformlng(lng - 105.0, lat - 35.0);
    		double radlat = lat / 180.0 * pi;
    		double magic = Math.sin(radlat);
    		magic = 1 - ee * magic * magic;
    		double sqrtmagic = Math.sqrt(magic);
    		dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi);
    		dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * pi);
    		double mglat = lat + dlat;
    		double mglng = lng + dlng;
    		return new double[] { lng * 2 - mglng, lat * 2 - mglat };
    	}
    
    	/**
    	 * 纬度转换
    	 * 
    	 * @param lng
    	 * @param lat
    	 * @return
    	 */
    	public static double transformlat(double lng, double lat) {
    		double ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
    		ret += (20.0 * Math.sin(6.0 * lng * pi) + 20.0 * Math.sin(2.0 * lng * pi)) * 2.0 / 3.0;
    		ret += (20.0 * Math.sin(lat * pi) + 40.0 * Math.sin(lat / 3.0 * pi)) * 2.0 / 3.0;
    		ret += (160.0 * Math.sin(lat / 12.0 * pi) + 320 * Math.sin(lat * pi / 30.0)) * 2.0 / 3.0;
    		return ret;
    	}
    
    	/**
    	 * 经度转换
    	 * 
    	 * @param lng
    	 * @param lat
    	 * @return
    	 */
    	public static double transformlng(double lng, double lat) {
    		double ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
    		ret += (20.0 * Math.sin(6.0 * lng * pi) + 20.0 * Math.sin(2.0 * lng * pi)) * 2.0 / 3.0;
    		ret += (20.0 * Math.sin(lng * pi) + 40.0 * Math.sin(lng / 3.0 * pi)) * 2.0 / 3.0;
    		ret += (150.0 * Math.sin(lng / 12.0 * pi) + 300.0 * Math.sin(lng / 30.0 * pi)) * 2.0 / 3.0;
    		return ret;
    	}
    
    	/**
    	 * 判断是否在国内,不在国内不做偏移
    	 * 
    	 * @param lng
    	 * @param lat
    	 * @return
    	 */
    	public static boolean out_of_china(double lng, double lat) {
    		if (lng < 72.004 || lng > 137.8347) {
    			return true;
    		} else if (lat < 0.8293 || lat > 55.8271) {
    			return true;
    		}
    		return false;
    	}
    }
    
    • 经纬度格式转换工具类
    /**
     * Created by liusj on 2019/5/27
     * <p>
     * 经纬度格式转换工具类.
     */
    public class CoordinateUtil {
    
        /**
         * 经纬度转化,度分秒转度.
         * 如:108°13′21″= 108.2225
         * @param jwd
         * @return
         */
        public static String DmsTurnDD(String jwd) {
            if (Strings.isNotEmpty(jwd) && (jwd.contains("°"))) {//如果不为空并且存在度单位
                //计算前进行数据处理
                jwd = jwd.replace("E", "").replace("N", "").replace(":", "").replace(":", "");
                double d = 0, m = 0, s = 0;
                d = Double.parseDouble(jwd.split("°")[0]);
                //不同单位的分,可扩展
                if (jwd.contains("′")) {//正常的′
                    m = Double.parseDouble(jwd.split("°")[1].split("′")[0]);
                } else if (jwd.contains("'")) {//特殊的'
                    m = Double.parseDouble(jwd.split("°")[1].split("'")[0]);
                }
                //不同单位的秒,可扩展
                if (jwd.contains("″")) {//正常的″
                    //有时候没有分 如:112°10.25″
                    s = jwd.contains("′") ? Double.parseDouble(jwd.split("′")[1].split("″")[0]) : Double.parseDouble(jwd.split("°")[1].split("″")[0]);
                } else if (jwd.contains("''")) {//特殊的''
                    //有时候没有分 如:112°10.25''
                    s = jwd.contains("'") ? Double.parseDouble(jwd.split("'")[1].split("''")[0]) : Double.parseDouble(jwd.split("°")[1].split("''")[0]);
                }
                jwd = String.valueOf(d + m / 60 + s / 60 / 60);//计算并转换为string
    
            }
            return jwd;
        }
    
        /**
         * 经纬度转换,度分转度度.
         * 如:112°30.4128 = 112.50688
         */
        public static String DmTurnDD(String jwd) {
            jwd = jwd.replace("′", "");
            if (Strings.isNotEmpty(jwd) && (jwd.contains("°"))) {//如果不为空并且存在度单位
                double d = 0, m = 0;
                d = Double.parseDouble(jwd.split("°")[0]);
                m = Double.parseDouble(jwd.split("°")[1]) / 60;
                jwd = String.valueOf(d + m);
            }
            return jwd;
        }
    }
    

    验证

    WGS84转GCJ02

    在这里插入图片描述

    • 工具类CoordinateTransformUtil
       double[] gcj02 = CoordinateTransformUtil.wgs84togcj02(116.481499, 39.990475);
       116.48758557081051,39.99175425467313
    

    结论:小数点后6位一致,在地图上是同一个点

    在这里插入图片描述

    百度坐标系(BD-09)转火星坐标系(GCJ-02)

    在这里插入图片描述

    • 工具类CoordinateTransformUtil
    double[] gcj02 = CoordinateTransformUtil.bd09togcj02(116.481499, 39.990475);
    
    116.47489604504428,39.98471586964859
    

    结论:小数点后6位一致,在地图上是同一个点

    WGS坐标转百度坐标系(BD-09)

    在这里插入图片描述

    • 工具类CoordinateTransformUtil
    double[] gcj02 = CoordinateTransformUtil.wgs84tobd09(114.21892734521,29.575429778924);
    
    114.23074697114104,29.5790799569647
    

    在这里插入图片描述

    结论:小数点后6位基本一致,在地图上是同一个点,这个误差非常非常小,可忽略不计

    火星坐标系(GCJ-02)转百度坐标系(BD-09)

    在这里插入图片描述

    • 工具类CoordinateTransformUtil
    double[] gcj02 = CoordinateTransformUtil.gcj02tobd09(114.21892734521,29.575429778924);
    114.22539195427781,29.5815853675143
    

    结论

    这个工具类CoordinateTransformUtil非常的nice,能达到生产级别的准度。

    参考:

    https://github.com/wandergis/coordtransform

    https://github.com/geosmart/coordtransform


    🍎QQ群【837324215
    🍎关注我的公众号【Java大厂面试官】,一起学习呗🍎🍎🍎
    🍎个人vxlakernote

    img

    展开全文
  • 各地图坐标转换工具

    千次阅读 2020-01-19 16:54:15
    * 坐标转换工具类 * WGS84坐标系:即地球坐标系,国际上通用的坐标系。Earth (GPS坐标系) * GCJ02坐标系:即火星坐标系,WGS84坐标系经加密后的坐标系。Mars (谷歌地图(中国)、高德地图、腾讯地图) * BD09坐标系...
  • java常用坐标转换

    2017-12-12 16:35:49
    /**  *  ... * @description:坐标转换处理工具  * @author zhoushanshan  * @version V1.0  */ public class CoordTransformUtil { public static double pi = 3.1415926535897932384626;
  • 已知两个点在两套坐标系的坐标,可以转换其他点
  • 经纬度坐标、瓦片坐标、图幅坐标转换工具 经纬度坐标范围转换为瓦片坐标范围 example: geo2tile([-180, 40, 170, 80],2); 图幅坐标范围转换为经纬度坐标范围 todo
  • Gps坐标转换Java工具类WGS坐标与Google和百度坐标互转,偏差很小,与百度Api调用转换几乎相差无几,程序为Java程序,工具类直接传经纬度调用相应转换方法即可获取转换后的返回值
  • 这个不是现成的工具,而是具体的Java语言代码功能实现。利用java语言实现了大地坐标系和空间直角坐标系的相互转换,以及求解七参数的值的方法。
  • 百度找了很多大部分都是pom的,maven项目中的,但是用maven下载不了,只能一个jar一个jar下载了,中间也遇到了很多坑,都是pom中没有提到的架包 ...import java.io.File; import java.io.IOException; import j...
  • java版GPS坐标转换为高德地图坐标

    热门讨论 2015-12-25 14:03:24
    此文件为纯java编写的GPS坐标转换到高德地图坐标,直接将文件添加到工程目录,调用转换函数即可,输入是double类型,输出是double数组,注意:输入输出数据的单位都是度。
  • GIS坐标转换 JAVA

    热门讨论 2011-12-12 10:22:03
    我是为了将EPSG:4326坐标转换成EPSG:900913坐标,找到的工具,然后添加了两者之间的转换方式! 使用方式: private static Projection proj = ProjectionFactory .getNamedPROJ4CoordinateSystem("epsg:900913");...
  • 坐标经纬度格式度 分 秒。转换为小数点样式113.xxxxxxxx

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 20,854
精华内容 8,341
关键字:

java坐标转换工具

java 订阅