地球坐标系、火星坐标系等相互转换、判断点是否在区域内(经纬度)工具类

地球坐标系、火星坐标系等相互转换、判断点是否在区域内(经纬度)工具类

1、坐标系种类简介
  1. WGS84坐标系
    即地球坐标系,国际上通用的坐标系。
    设备一般包含GPS芯片或者北斗芯片获取的经纬度为WGS84地理坐标系。谷歌地图采用的是WGS84地理坐标系(中国范围除外,谷歌中国地图采用的是GCJ02地理坐标系。)

  2. GCJ02坐标系
    即火星坐标系,WGS84坐标系经加密后的坐标系。
    出于国家安全考虑,国内所有导航电子地图必须使用国家测绘局制定的加密坐标系统,即将一个真实的经纬度坐标加密成一个不正确的经纬度坐标。

  3. BD09坐标系
    即百度坐标系,GCJ02坐标系经加密后的坐标系。搜狗坐标系、图吧坐标系等,估计也是在GCJ02基础上加密而成的。

  4. 各主流地图API采用的坐标系
    高德MapABC地图API 火星坐标
    腾讯搜搜地图API 火星坐标
    阿里云地图API 火星坐标
    灵图51ditu地图API 火星坐标

    百度地图API 百度坐标
    搜狐搜狗地图API 搜狗坐标
    图吧MapBar地图API 图吧坐标

2、坐标系转换、判断坐标点是否在区域内 工具类
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;

import java.awt.geom.Path2D;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 地球坐标系、火星坐标系等相互转换、判断点是否在区域内
 *
 * @Author: pdx
 * @Date: 2023/2/24 9:04
 * @Version 1.0
 */

/**
 * 地球坐标系 (WGS-84) 相互转火星坐标系 (GCJ-02) 的转换算法
 * <p>
 * 1.各坐标系简介
 * WGS84坐标系
 * 即地球坐标系,国际上通用的坐标系。
 * 设备一般包含GPS芯片或者北斗芯片获取的经纬度为WGS84地理坐标系。谷歌地图采用的是WGS84地理坐标系(中国范围除外,谷歌中国地图采用的是GCJ02地理坐标系。)
 * <p>
 * GCJ02坐标系
 * 即火星坐标系,WGS84坐标系经加密后的坐标系。
 * 出于国家安全考虑,国内所有导航电子地图必须使用国家测绘局制定的加密坐标系统,即将一个真实的经纬度坐标加密成一个不正确的经纬度坐标。
 * <p>
 * BD09坐标系
 * 即百度坐标系,GCJ02坐标系经加密后的坐标系。搜狗坐标系、图吧坐标系等,估计也是在GCJ02基础上加密而成的。
 * <p>
 * 各主流地图API采用的坐标系
 * 高德MapABC地图API 火星坐标
 * 腾讯搜搜地图API 火星坐标
 * 阿里云地图API 火星坐标
 * 灵图51ditu地图API 火星坐标
 * <p>
 * 百度地图API 百度坐标
 * 搜狐搜狗地图API 搜狗坐标
 * 图吧MapBar地图API 图吧坐标
 */
public class CoordinatesPointUtil {

    /**
     * 圆周率
     */
    private static double pi = 3.14159265358979324D;
    /**
     * WGS 长轴半径
     */
    private static double a = 6378245.0D;
    /**
     * WGS 偏心率的平方
     */
    private static double ee = 0.00669342162296594323D;

    private static double x_pi = 3.14159265358979324 * 3000.0 / 180.0;


    /**
     * 84->gcj02
     * 地球坐标系 -> 火星坐标系
     *
     * @param lon 经度
     * @param lat 纬度
     * @return
     */
    public static Map<String, Double> transform(double lon, double lat) {
        HashMap<String, Double> localHashMap = new HashMap<String, Double>();
        if (outofChina(lat, lon)) {
            localHashMap.put("lon", Double.valueOf(lon));
            localHashMap.put("lat", Double.valueOf(lat));
            return localHashMap;
        }
        double dLat = transformLat(lon - 105.0, lat - 35.0);
        double dLon = transformLon(lon - 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);
        dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
        double mgLat = lat + dLat;
        double mgLon = lon + dLon;
        localHashMap.put("lon", mgLon);
        localHashMap.put("lat", mgLat);
        return localHashMap;
    }

    // gcj02-84

    /**
     * gcj02 -> 84
     * 火星坐标系 -> 地球坐标系
     *
     * @param lon 经度
     * @param lat 纬度
     * @return
     */
    public static Map<String, Double> gcj2wgs(double lon, double lat) {
        Map<String, Double> localHashMap = new HashMap<String, Double>();
        double lontitude = lon
                - (((Double) transform(lon, lat).get("lon")).doubleValue() - lon);
        double latitude = (lat - (((Double) (transform(lon, lat)).get("lat"))
                .doubleValue() - lat));
        localHashMap.put("lon", lontitude);
        localHashMap.put("lat", latitude);
        return localHashMap;
    }

    /**
     * 火星坐标转换为百度坐标
     *
     * @param gg_lon 经度
     * @param gg_lat 纬度
     */
    public static Map<String, Double> bd_encrypt(double gg_lon, double gg_lat) {
        Map<String, Double> bdlocalHashMap = new HashMap<String, Double>();
        double x = gg_lon, y = gg_lat;
        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 bd_lon = z * Math.cos(theta) + 0.0065;
        double bd_lat = z * Math.sin(theta) + 0.006;
        bdlocalHashMap.put("lon", bd_lon);
        bdlocalHashMap.put("lat", bd_lat);
        return bdlocalHashMap;
    }

    /**
     * 84转百度
     * 地球转百度
     *
     * @param longitude 经度
     * @param latitude  纬度
     * @return
     */
    public static Map<String, Double> wgs84_bd09(double longitude, double latitude) {
        //1,将84转国测局gcj-02
        Map<String, Double> mapForGCJ = transform(longitude, latitude);
        Double lonGCJ = mapForGCJ.get("lon");
        Double latGCJ = mapForGCJ.get("lat");
        //2.将gcj-02转百度
        Map<String, Double> mapForBD09 = bd_encrypt(latGCJ, lonGCJ);
        return mapForBD09;
    }

    /**
     * 百度转 火星 gcj02
     */
    public static Map<String, Double> bd09togcj02(double bd_lon, double bd_lat) {
        Map<String, Double> bdtogcmap = new HashMap<>();
        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);
        bdtogcmap.put("lon", gg_lng);
        bdtogcmap.put("lat", gg_lat);
        return bdtogcmap;
    }

    /**
     * 百度转 地球84
     */
    public static Map<String, Double> bd09to84(double bd_lon, double bd_lat) {
        Map<String, Double> bdtogcmap = bd09togcj02(bd_lon, bd_lat);
        Double lon = bdtogcmap.get("lon");
        Double lat = bdtogcmap.get("lat");

        Map<String, Double> gcto84map = gcj2wgs(lon, lat);
        return gcto84map;
    }


    /**
     * 判断点是否在区域内
     *
     * @param polygon   区域经纬度json字符串
     * @param longitude 经度
     * @param latitude  纬度
     * @return 返回true跟false
     */

    public static boolean isPoint(String polygon, double longitude, double latitude) {

        JSONArray jsonArray = JSON.parseArray(polygon);

        //将json转换成对象

        List<ScopeRequest> list = JSON.parseArray(jsonArray.toJSONString(), ScopeRequest.class);

        Path2D path2D = create(list);

        //true如果指定的坐标在Shape边界内; 否则为false 。

        return path2D.contains(longitude, latitude);

    }

    /**
     * 使用Path2D创建一个多边形
     *
     * @param polygon 经纬度 集合
     * @return 返回Path2D.Double
     */
    private static Path2D.Double create(List<ScopeRequest> polygon) {

        //创建path2D对象

        Path2D.Double generalPath = new Path2D.Double();

        //获取第一个起点经纬度的坐标

        ScopeRequest first = polygon.get(0);

        //通过移动到以double精度指定的指定坐标,把第一个起点添加到路径中

        generalPath.moveTo(first.getLongitude(), first.getLatitude());

        //把集合中的第一个点删除防止重复添加

        polygon.remove(0);

        //循环集合里剩下的所有经纬度坐标

        for (ScopeRequest d : polygon) {

            //通过从当前坐标绘制直线到以double精度指定的新指定坐标,将路径添加到路径。

            //从第一个点开始,不断往后绘制经纬度点

            generalPath.lineTo(d.getLongitude(), d.getLatitude());

        }

        // 最后要多边形进行封闭,起点及终点

        generalPath.lineTo(first.getLongitude(), first.getLatitude());

        //将直线绘制回最后一个 moveTo的坐标来关闭当前子路径。

        generalPath.closePath();

        return generalPath;

    }

    /**
     * 中国坐标内
     *
     * @param lat 纬度
     * @param lon 经度
     * @return
     */
    public static boolean outofChina(double lat, double lon) {
        if (lon < 72.004 || lon > 137.8347) {
            return true;
        }
        if (lat < 0.8293 || lat > 55.8271) {
            return true;
        }
        return false;
    }

    public static double transformLat(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 * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
        ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
        return ret;
    }


    public static double transformLon(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 * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
        ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0
                * pi)) * 2.0 / 3.0;
        return ret;
    }
}

实体类

public class ScopeRequest {
    private Double longitude;
    private Double latitude;
    public ScopeRequest() {
    }
    public ScopeRequest(Double longitude, Double latitude) {
        this.longitude = longitude;
        this.latitude = latitude;
    }
}
3、使用
    public void testPoint() {

        Double longitude = 113.73833333333333;
        Double latitude = 22.856666666666666;

        //判断坐标是否在指定范围内
        //区域指标
        String area = "[{\"longitude\":113.65052685099445,\"latitude\":22.824908507785644},{\"longitude\":113.64822626450176,\"latitude\":22.825632039022434},{\"longitude\":113.6399128216911,\"latitude\":22.828378879748556},{\"longitude\":113.63436153664783,\"latitude\":22.831287250224182},{\"longitude\":113.62905789669807,\"latitude\":22.836129327366223},{\"longitude\":113.62624769320206,\"latitude\":22.833767617021206},{\"longitude\":113.62267410116758,\"latitude\":22.825636897577045},{\"longitude\":113.61849358338274,\"latitude\":22.820459394024212},{\"longitude\":113.61170820364872,\"latitude\":22.81444546219262},{\"longitude\":113.61023296850541,\"latitude\":22.813297131119313},{\"longitude\":113.60859390988011,\"latitude\":22.811893708506787},{\"longitude\":113.60552826677758,\"latitude\":22.809416442845645},{\"longitude\":113.60607541430429,\"latitude\":22.808786194249834},{\"longitude\":113.60650800900952,\"latitude\":22.808211180848325},{\"longitude\":113.60734124334928,\"latitude\":22.80722299621359},{\"longitude\":113.6103369623189,\"latitude\":22.803566715667042},{\"longitude\":113.64682541465535,\"latitude\":22.75743868593322},{\"longitude\":113.65825492099916,\"latitude\":22.741973885420492},{\"longitude\":113.67124736855725,\"latitude\":22.72594653992477},{\"longitude\":113.68077546696753,\"latitude\":22.717980884824186},{\"longitude\":113.70999444238491,\"latitude\":22.726834382110745},{\"longitude\":113.74515164674901,\"latitude\":22.729278187166013},{\"longitude\":113.74880700731542,\"latitude\":22.73431125977091},{\"longitude\":113.75458539183593,\"latitude\":22.74008256841958},{\"longitude\":113.76528919525289,\"latitude\":22.747602720473147},{\"longitude\":113.76663725001177,\"latitude\":22.750796930182933},{\"longitude\":113.76288734236499,\"latitude\":22.753108710176157},{\"longitude\":113.75782468997326,\"latitude\":22.74867996266583},{\"longitude\":113.74971607616936,\"latitude\":22.757151590356145},{\"longitude\":113.750600834551,\"latitude\":22.759037096438643},{\"longitude\":113.74099704115042,\"latitude\":22.761293726841227},{\"longitude\":113.73325408167987,\"latitude\":22.765064845081536},{\"longitude\":113.72826272961547,\"latitude\":22.76570054906868},{\"longitude\":113.72296538647286,\"latitude\":22.769050441372162},{\"longitude\":113.71939633949256,\"latitude\":22.777781945014027},{\"longitude\":113.72022682667533,\"latitude\":22.775879453838286},{\"longitude\":113.71931147732288,\"latitude\":22.779681081681755},{\"longitude\":113.71437131534617,\"latitude\":22.7867011908682},{\"longitude\":113.70919178027418,\"latitude\":22.78877673250503},{\"longitude\":113.70602977734606,\"latitude\":22.791815078563502},{\"longitude\":113.70333053581464,\"latitude\":22.796790345308064},{\"longitude\":113.69767490739432,\"latitude\":22.80131284144102},{\"longitude\":113.70221068374987,\"latitude\":22.805504603992116},{\"longitude\":113.70020631731316,\"latitude\":22.810803734698652},{\"longitude\":113.7065022894591,\"latitude\":22.810239593076517},{\"longitude\":113.7069975799168,\"latitude\":22.806342887679417},{\"longitude\":113.71030467414265,\"latitude\":22.804881724080417},{\"longitude\":113.71542722281255,\"latitude\":22.805137453931366},{\"longitude\":113.71630227187349,\"latitude\":22.807419030643644},{\"longitude\":113.72116408395344,\"latitude\":22.805420677543058},{\"longitude\":113.72632814010831,\"latitude\":22.806991341644956},{\"longitude\":113.72727458299788,\"latitude\":22.810463838914416},{\"longitude\":113.7244737772436,\"latitude\":22.81388034028834},{\"longitude\":113.72920863045192,\"latitude\":22.814642248968315},{\"longitude\":113.73411011556037,\"latitude\":22.811084814139633},{\"longitude\":113.73601745531245,\"latitude\":22.805872591111154},{\"longitude\":113.74346235660745,\"latitude\":22.807673875160898},{\"longitude\":113.74823545804544,\"latitude\":22.809449427719752},{\"longitude\":113.74892951397094,\"latitude\":22.815132336016408},{\"longitude\":113.75619359061737,\"latitude\":22.824122242787382},{\"longitude\":113.75795391011285,\"latitude\":22.82193420516432},{\"longitude\":113.76357739774382,\"latitude\":22.82163055337918},{\"longitude\":113.76417143565757,\"latitude\":22.82410102899934},{\"longitude\":113.76797854563756,\"latitude\":22.823145212921872},{\"longitude\":113.77126436385585,\"latitude\":22.82568209098946},{\"longitude\":113.77452356590061,\"latitude\":22.832758785166046},{\"longitude\":113.78462710136652,\"latitude\":22.83595616626837},{\"longitude\":113.78443235927783,\"latitude\":22.838100022544666},{\"longitude\":113.7889734728652,\"latitude\":22.838424015560403},{\"longitude\":113.79432050990738,\"latitude\":22.843153430070345},{\"longitude\":113.79708798233801,\"latitude\":22.841214376946425},{\"longitude\":113.79861272420509,\"latitude\":22.8433198572514},{\"longitude\":113.80316636576548,\"latitude\":22.845559693832286},{\"longitude\":113.80668843751758,\"latitude\":22.849121956562612},{\"longitude\":113.80229163247365,\"latitude\":22.858728423098285},{\"longitude\":113.79997674217155,\"latitude\":22.858377966133332},{\"longitude\":113.79178715051151,\"latitude\":22.86128085444187},{\"longitude\":113.7844243413804,\"latitude\":22.865623245056952},{\"longitude\":113.78018269150832,\"latitude\":22.873340907123577},{\"longitude\":113.7732358228895,\"latitude\":22.87530659748961},{\"longitude\":113.77195465643565,\"latitude\":22.88149455602678},{\"longitude\":113.77021731594355,\"latitude\":22.88335211694772},{\"longitude\":113.76933967082468,\"latitude\":22.888039355072976},{\"longitude\":113.76863224172449,\"latitude\":22.88629615718367},{\"longitude\":113.7607629470999,\"latitude\":22.882644205114726},{\"longitude\":113.76011987158208,\"latitude\":22.882382719024008},{\"longitude\":113.75701504616109,\"latitude\":22.88219862477962},{\"longitude\":113.7561130750375,\"latitude\":22.881958604389013},{\"longitude\":113.75368922065934,\"latitude\":22.881706349829415},{\"longitude\":113.75151270892913,\"latitude\":22.88053618976846},{\"longitude\":113.75013375026039,\"latitude\":22.877429003852622},{\"longitude\":113.7483828609701,\"latitude\":22.877070388817174},{\"longitude\":113.74835316962547,\"latitude\":22.877060317707},{\"longitude\":113.74748444375044,\"latitude\":22.876595770107656},{\"longitude\":113.74718684314381,\"latitude\":22.875935086370983},{\"longitude\":113.74659395283433,\"latitude\":22.875390588612447},{\"longitude\":113.7435562206671,\"latitude\":22.873361164863233},{\"longitude\":113.73726288038131,\"latitude\":22.87337002472378},{\"longitude\":113.73054478636325,\"latitude\":22.872310717168144},{\"longitude\":113.72765235615658,\"latitude\":22.873782264984413},{\"longitude\":113.72127603124866,\"latitude\":22.869658961753093},{\"longitude\":113.720753517223,\"latitude\":22.866053248987214},{\"longitude\":113.7175565395653,\"latitude\":22.86519451974749},{\"longitude\":113.71751196019294,\"latitude\":22.86691008829194},{\"longitude\":113.72163262968266,\"latitude\":22.870352246603602},{\"longitude\":113.71963919248458,\"latitude\":22.872499653587564},{\"longitude\":113.72350584035668,\"latitude\":22.87402977595593},{\"longitude\":113.72562760295729,\"latitude\":22.876307375631374},{\"longitude\":113.72514222982332,\"latitude\":22.879568712481728},{\"longitude\":113.72618458919005,\"latitude\":22.881755081656475},{\"longitude\":113.72319930045549,\"latitude\":22.881014022484408},{\"longitude\":113.72250430680228,\"latitude\":22.882003730420305},{\"longitude\":113.72247157532843,\"latitude\":22.882025989820818},{\"longitude\":113.72067163773507,\"latitude\":22.88235111316067},{\"longitude\":113.71698915656086,\"latitude\":22.881341694090903},{\"longitude\":113.7139312819414,\"latitude\":22.880050832295467},{\"longitude\":113.7129685467066,\"latitude\":22.879464018740407},{\"longitude\":113.71189166124292,\"latitude\":22.879033835846997},{\"longitude\":113.71147070720534,\"latitude\":22.879049166613356},{\"longitude\":113.7084584772929,\"latitude\":22.88054059116558},{\"longitude\":113.7069555786569,\"latitude\":22.879841877320022},{\"longitude\":113.7040370354356,\"latitude\":22.878636885007722},{\"longitude\":113.7035370837592,\"latitude\":22.87996078003101},{\"longitude\":113.70089455992375,\"latitude\":22.881480153053417},{\"longitude\":113.69894148955734,\"latitude\":22.881723210971188},{\"longitude\":113.69514856033632,\"latitude\":22.881089807647474},{\"longitude\":113.69032239425738,\"latitude\":22.88100403451165},{\"longitude\":113.68921936200641,\"latitude\":22.880442644743372},{\"longitude\":113.68864242766834,\"latitude\":22.8802094098441},{\"longitude\":113.68030193530545,\"latitude\":22.877561381164014},{\"longitude\":113.67666553694984,\"latitude\":22.87347738229181},{\"longitude\":113.66952334413088,\"latitude\":22.871252574688924},{\"longitude\":113.66650103295731,\"latitude\":22.869191048370737},{\"longitude\":113.6646295746507,\"latitude\":22.870690917897093},{\"longitude\":113.65977442088264,\"latitude\":22.868160189734795},{\"longitude\":113.65302379554976,\"latitude\":22.862724062702853},{\"longitude\":113.65020156053536,\"latitude\":22.861883535544795},{\"longitude\":113.65063013937888,\"latitude\":22.860886732643966},{\"longitude\":113.65063687187568,\"latitude\":22.859881865554826},{\"longitude\":113.64789060847237,\"latitude\":22.858722154937706},{\"longitude\":113.6450396121887,\"latitude\":22.855627431028722},{\"longitude\":113.64594409174539,\"latitude\":22.85403127492708},{\"longitude\":113.64686949816641,\"latitude\":22.852271360786233},{\"longitude\":113.64772936891379,\"latitude\":22.849684264752113},{\"longitude\":113.6478426236727,\"latitude\":22.847606197644783},{\"longitude\":113.64809338050058,\"latitude\":22.84204754568185},{\"longitude\":113.64892440468782,\"latitude\":22.839447861568377},{\"longitude\":113.65002297762257,\"latitude\":22.83709937475891},{\"longitude\":113.65100680212483,\"latitude\":22.8339922280382},{\"longitude\":113.64983257690167,\"latitude\":22.83001438108181},{\"longitude\":113.64864259124752,\"latitude\":22.830822313976626},{\"longitude\":113.64888568262346,\"latitude\":22.82931645042493},{\"longitude\":113.64904612048065,\"latitude\":22.825430893847116},{\"longitude\":113.65052685099445,\"latitude\":22.824908507785644}]";
        boolean point = CoordinatesPointUtil.isPoint(area, longitude, latitude);
        System.out.println("坐标是否在指定范围内:" + point);

//        坐标系转换
        Map<String, Double> stringDoubleMap = CoordinatesPointUtil.gcj2wgs(longitude, latitude);
        System.out.println("转换后坐标系:" + stringDoubleMap.toString());
    }

参考:

https://blog.csdn.net/ThinkWon/article/details/101392187

https://zhuanlan.zhihu.com/p/363528840

https://nowjava.com/docs/java-api-11/java.desktop/java/awt/geom/Path2D.html

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值