shenyijian
2023-12-02 33f0d90125ce9f5b572444bc4daeae1fe5bb4937
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
package com.dji.sample.geo.utils;
 
import com.dji.sample.geo.entity.Feature;
import com.dji.sample.geo.entity.GeoJson;
import com.dji.sample.wayline.model.param.FlyAreaParam;
import com.dji.sample.wayline.model.param.PointPOJO;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
 
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
 
/**
 * 空间计算工具类
 */
public class GeoUtils {
    /**
     * 默认地球半径
     */
    private static double EARTH_RADIUS = 6371000;//赤道半径(单位m)
 
    /**
     * 转化为弧度(rad)
     */
    private static double rad(double d) {
        return d * Math.PI / 180.0;
    }
 
 
    /**
     * 计算中心经纬度与目标经纬度的距离(米)
     *
     * @param centerLon 中心精度
     * @param centerLat 中心纬度
     * @param targetLon 需要计算的精度
     * @param targetLat 需要计算的纬度
     * @return 米
     */
    public static double distance(double centerLon, double centerLat, double targetLon, double targetLat) {
 
        double jl_jd = 102834.74258026089786013677476285;// 每经度单位米;
        double jl_wd = 111712.69150641055729984301412873;// 每纬度单位米;
        double b = Math.abs((centerLat - targetLat) * jl_jd);
        double a = Math.abs((centerLon - targetLon) * jl_wd);
        return Math.sqrt((a * a + b * b));
    }
 
    /**
     * 根据多个点计算中心点
     * @param list
     * @return
     */
    public static PointPOJO getCenterPoint(List<PointPOJO> list) {
 
        int total = list.size();
        double X = 0, Y = 0, Z = 0;
 
        for (int i = 0; i < list.size(); i++) {
            PointPOJO point = list.get(i);
            double lat, lon, x, y, z;
            lon = point.getLon() * Math.PI / 180;
            lat = point.getLat() * Math.PI / 180;
            x = Math.cos(lat) * Math.cos(lon);
            y = Math.cos(lat) * Math.sin(lon);
            z = Math.sin(lat);
            X += x;
            Y += y;
            Z += z;
        }
 
 
        X = X / total;
        Y = Y / total;
        Z = Z / total;
        double Lon = Math.atan2(Y, X);
        double Hyp = Math.sqrt(X * X + Y * Y);
        double Lat = Math.atan2(Z, Hyp);
 
        PointPOJO centerPoint = new PointPOJO();
        centerPoint.setLon( Lon * 180 / Math.PI);
        centerPoint.setLat(Lat * 180 / Math.PI);
        return centerPoint;
    }
 
    /**
     * 获取点区域并按从近到远排序
     * @param flyAreaParam
     * @return
     */
    public static List<PointPOJO> caculatePointList(FlyAreaParam flyAreaParam){
        List<List<PointPOJO>> areaList = flyAreaParam.getAreaList();
        PointPOJO dockPoint = flyAreaParam.getDockPoint();
        Double radius = flyAreaParam.getRadius();
 
        List<PointPOJO> centerPointList = new ArrayList<>();
 
        //根据区域获取中心点
        areaList.forEach(area -> {
            PointPOJO centerPoint = GeoUtils.getCenterPoint(area);
            centerPointList.add(centerPoint);
        });
 
        //巡逻目标集合
        List<PointPOJO> targetList = new ArrayList<>();
        //获取所有中心点之后,
        centerPointList.forEach(centerPoint -> {
            //判断各个中心点和机场点的距离
            double distance = GeoUtils.distance(dockPoint.getLon(), dockPoint.getLat(), centerPoint.getLon(), centerPoint.getLat());
 
            //当距离小于半径时,添加到目标集合中
            if (distance <= radius) {
                centerPoint.setDistance(distance);
                targetList.add(centerPoint);
            }
        });
 
        //按距离从近到远排序
        targetList.sort(Comparator.comparing(PointPOJO::getDistance));
        return targetList;
    }
 
    /**
     * 根据geojson获取点区域并按从近到远排序
     * @param geoJson
     * @return
     */
    public static List<PointPOJO> caculatePointList(GeoJson geoJson,PointPOJO dockPoint,Double radius){
        List<Feature> features = geoJson.getFeatures();
 
        List<List<PointPOJO>> areaList = new ArrayList<>();
 
        features.forEach(feature -> {
            List<PointPOJO> list = new ArrayList<>();
            List<List<Double>> coordinates = feature.getGeometry().getCoordinates().get(0);
 
            coordinates.forEach(coordinate ->{
                PointPOJO pointPOJO = new PointPOJO();
 
                pointPOJO.setLon(coordinate.get(0));
                pointPOJO.setLat(coordinate.get(1));
 
                list.add(pointPOJO);
            });
            areaList.add(list);
        });
 
        FlyAreaParam flyAreaParam = new FlyAreaParam();
 
        flyAreaParam.setDockPoint(dockPoint);
        flyAreaParam.setRadius(radius);
        flyAreaParam.setAreaList(areaList);
 
        List<PointPOJO> pointPOJOS = caculatePointList(flyAreaParam);
 
        return pointPOJOS;
    }
 
    /**
     * 读取json文件
     * @param path
     * @return
     */
    public static GeoJson readJsonFile(String path){
 
        try {
            File file = new File(path);
            ObjectMapper objectMapper = new ObjectMapper();
 
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
 
            return objectMapper.readValue(file, GeoJson.class);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
 
    }
 
}