MrShi
2025-09-15 856f526f823f5dad88c28657d82f971ff66afb1e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
package com.doumee.core.utils;
 
 
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.doumee.dao.business.web.request.LocaltionDTO;
 
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
 
/**
 * 计算距离
 */
public class PositionUtil {
 
 
 
 
    public static String getTxMapAddrByLatAndLng(Double lat,Double lng,String host,String mapkey){
        try {
            if(lat == null || lng ==null){
                return null;
            }
            String url =host +"/ws/geocoder/v1/?key="+mapkey+"&location="+lat+","+lng;
            String res = HttpsUtil.get(url,false);
            JSONObject jsonObject = JSONObject.parseObject(res );
           String r = null;
           if(jsonObject.getJSONObject("result")!=null){
               if(jsonObject.getJSONObject("result").getJSONObject("formatted_addresses")!=null){
                   r =jsonObject.getJSONObject("result").getJSONObject("formatted_addresses").getString("recommend");
               }
               if(r==null || r.equals("")){
                   r =jsonObject.getJSONObject("result").getString("address");
               }
           }
           return r;
 
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 椭球参数
     */
    private static double pi = 3.14159265358979324;
    /**
     * 卫星椭球坐标投影到平面地图坐标系的投影因子
     */
    private static double a = 6378245.0;
    /**
     * 椭球的偏心率
     */
    private static double ee = 0.00669342162296594323;
 
    /**
     * 经纬度 GPS转高德
     *
     * @param wgLon GPS经度
     * @param wgLat GPS维度
     * @return 转化后的经纬度坐标
     */
    public static AMap transform(double wgLon, double wgLat) {
        if (outOfChina(wgLat, wgLon)) {
            return new AMap(wgLon, wgLat);
        }
 
        double dLat = transformLat(wgLon - 105.0, wgLat - 35.0);
        double dLon = transformLon(wgLon - 105.0, wgLat - 35.0);
        double radLat = wgLat / 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 transLat = wgLat + dLat;
        double transLon = wgLon + dLon;
        return new AMap(transLon, transLat);
    }
 
    /**
     * 判断是否为国外坐标,,不在国内不做偏移
     *
     * @param lat
     * @param lon
     * @return
     */
    private 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;
    }
 
    /**
     * 纬度转换
     *
     * @param x
     * @param y
     * @return
     */
    private 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;
    }
 
    /**
     * 经度转换
     *
     * @param x
     * @param y
     * @return
     */
    private 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 static class AMap {
        /**
         * 经度
         */
        private double longitude;
 
        /**
         * 维度
         */
        private double latitude;
 
        public AMap(double longitude, double latitude) {
            this.longitude = longitude;
            this.latitude = latitude;
        }
 
        public double getLongitude() {
            return longitude;
        }
 
        public double getLatitude() {
            return latitude;
        }
    }
    public static void main(String[] args) {
//        System.out.println(
//          PositionUtil.getTxMapAddrByLatAndLng(Double.valueOf("31.76792509"),Double.valueOf("117.23267758"),"https://apis.map.qq.com","3AYBZ-I5R3V-2BVP3-UWBDQ-ETBM5-B2BBQ")
//        );
 
//        String str ="[{\"lat\":31.732726766273103,\"lng\":117.37721605116087,\"height\":0},{\"lat\":31.72079687406289,\"lng\":117.39831914258241,\"height\":0},{\"lat\":31.714484720597493,\"lng\":117.39831914258241,\"height\":0},{\"lat\":31.71233192243245,\"lng\":117.39583137996954,\"height\":0},{\"lat\":31.71401037878662,\"lng\":117.3785457182995,\"height\":0}]";
//        TypeReference typeReference =  new TypeReference<List<LocaltionDTO>>(){};
//        List<LocaltionDTO> array = JSONObject.parseObject(str, typeReference.getType());
//        if(array == null || array.size() ==0){
//           System.out.println("=================");
//        }
//        System.out.println(isInPolygon(  117.39387876,31.71365546,array));
//        AMap aMap = transform( 117.38823300,  31.71550000);
//        System.out.println(aMap.getLatitude()+""+aMap.getLongitude());
//        System.out.println(isInPolygon(  aMap.getLongitude(),aMap.getLatitude(),array));
    }
   /* "latitude": 31.71553300,
            "longitude": 117.39,
117.393962,31.713690
            31.71550000    117.38823300
   */ /**
     * 判断坐标点是否在多边形区域内
     *
     * @param pointLon 要判断的点的经度
     * @param pointLat 要判断的点的纬度
     * @return true:范围内; false:范围外
     */
    public static boolean isInPolygon(double pointLon, double pointLat, List<LocaltionDTO> list) {
        if(list==null ||list.size()==0){
            return false;
        }
        double[] lon = new double[list.size()];
        double[] lat = new double[list.size()];
        for (int i = 0; i < list.size(); i++) {
            lon[i] = list.get(i).getLng() ==null?0:list.get(i).getLng();
            lat[i] = list.get(i).getLat() ==null?0:list.get(i).getLat();
        }
        // 将要判断的横纵坐标组成一个点
        Point2D.Double point = new Point2D.Double(pointLon, pointLat);
        // 将区域各顶点的横纵坐标放到一个点集合里面
        List<Point2D.Double> pointList = new ArrayList<>();
        double polygonPointToX;
        double polygonPointToY;
        for (int i = 0; i < lon.length; i++) {
            polygonPointToX = lon[i];
            polygonPointToY = lat[i];
            Point2D.Double polygonPoint = new Point2D.Double(polygonPointToX, polygonPointToY);
            pointList.add(polygonPoint);
        }
        return check(point, pointList);
    }
 
    /**
     * 坐标点是否在多边形内
     *
     * @param point   要判断的点的横纵坐标
     * @param polygon 组成的顶点坐标集合
     */
    private static boolean check(Point2D.Double point, List<Point2D.Double> polygon) {
        GeneralPath generalPath = new GeneralPath();
 
        Point2D.Double first = polygon.get(0);
        // 通过移动到指定坐标(以双精度指定),将一个点添加到路径中
        generalPath.moveTo(first.x, first.y);
        polygon.remove(0);
        for (Point2D.Double d : polygon) {
            // 通过绘制一条从当前坐标到新指定坐标(以双精度指定)的直线,将一个点添加到路径中。
            generalPath.lineTo(d.x, d.y);
        }
        // 将几何多边形封闭
        generalPath.lineTo(first.x, first.y);
        generalPath.closePath();
        // 测试指定的 Point2D 是否在 Shape 的边界内。
        return generalPath.contains(point);
    }
 
}