aijinhui
2024-01-14 e9582af916d019c4695b0aaf9665039be1bd6ea1
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
package com.ruoyi.utils.tube;
 
import com.ruoyi.alarmpoints.tube.domain.ArdTubesDetails;
import com.ruoyi.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GeodeticCalculator;
import org.gavaghan.geodesy.GlobalCoordinates;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.TreeMap;
 
/**
 * @ClassName TubeTools
 * @Description: 管线计算工具
 * @Author 刘苏义
 * @Date 2023/6/6 19:29
 * @Version 1.0
 */
@Service
@Slf4j
public class TubeTools {
    public static void main(String[] args) {
        // 假设给定的三个坐标点 A、B、C
        GeoPoint pointA = new GeoPoint(124.939903268, 46.684520056, 143.3 - 0.73);
        GeoPoint pointB = new GeoPoint(124.94034787826001, 46.68444909044429, 144.12232823014708);
        GeoPoint pointC = new GeoPoint(124.940552075, 46.684416498, 144.5 - 0.81);
 
        double distance = getDistance(pointA, pointC);
        double diffAC = pointA.getAltitude() - pointC.getAltitude();
        log.info("AC总距离:" + distance + " AC高度差:" + diffAC);
        double distance1 = getDistance(pointA, pointB);
        double diffAB = pointA.getAltitude() - pointB.getAltitude();
        log.info("AB距离:" + distance1 + " AB高度差:" + diffAB);
        double distance2 = getDistance(pointB, pointC);
        double diffBC = pointB.getAltitude() - pointC.getAltitude();
        log.info("BC距离:" + distance2 + " BC高度差:" + diffBC);
        // 计算斜率
        double slope1 = (pointB.getLatitude() - pointA.getLatitude()) / (pointB.getLongitude() - pointA.getLongitude());
        double slope2 = (pointC.getLatitude() - pointB.getLatitude()) / (pointC.getLongitude() - pointB.getLongitude());
 
        // 设置斜率差值的阈值
        double threshold = 0.000001;
 
        // 检查斜率是否相等
        if (Math.abs(slope1 - slope2) < threshold) {
            log.debug("这三个点共线");
        } else {
            log.debug("这三个点不共线");
        }
    }
 
    /**
     *  计算坐标
     *
     *  刘苏义
     *  2023/6/8 14:38
     */
    public static GeoPoint CalculateCoordinates(List<ArdTubesDetails> ardTubesDetails, Integer alarmPointDistance) {
            try {
                if(StringUtils.isNull(alarmPointDistance))
                {
                    log.debug("报警点距离为空,无法计算坐标");
                    return null;
                }
                Comparator<ArdTubesDetails> comparator = Comparator.comparingInt(person -> Integer.parseInt(person.getInflectionPointNumber())); // 使用Collections.sort方法进行排序
                Collections.sort(ardTubesDetails, comparator);
                GeoPoint point0 = new GeoPoint(ardTubesDetails.get(0).getLongitude(), ardTubesDetails.get(0).getLatitude(), ardTubesDetails.get(0).getAltitude() - ardTubesDetails.get(0).getDepth());
                TreeMap<Integer, Double> distanceMap = new TreeMap<>();
                TreeMap<Integer, Object> tubeMap = new TreeMap<>();
                double distance = 0.0;
                for (ArdTubesDetails atd : ardTubesDetails) {
                    GeoPoint point = new GeoPoint(atd.getLongitude(), atd.getLatitude(), atd.getAltitude() - atd.getDepth());
                    distance += getDistance(point, point0);
                    distanceMap.put(Integer.parseInt(atd.getInflectionPointNumber()), distance);
                    tubeMap.put(Integer.parseInt(atd.getInflectionPointNumber()), atd);
                    point0 = point;
                }
                Integer num = 0;
                double tempDistance = 0.0;
                while (tempDistance < alarmPointDistance) {
                    num++;
                    tempDistance = distanceMap.get(num);
                }
                log.debug("报警点在拐点" + (num - 1) + "-" + num + "之间,总距离" + (tempDistance - distanceMap.get(num - 1)));
                ArdTubesDetails point1 = (ArdTubesDetails) tubeMap.get(num - 1);
                double x0 = point1.getLongitude();
                double y0 = point1.getLatitude();
                double z0 = point1.getAltitude();
                ArdTubesDetails point2 = (ArdTubesDetails) tubeMap.get(num);
                double x1 = point2.getLongitude();
                double y1 = point2.getLatitude();
                double z1 = point2.getAltitude();
                /*计算报警点坐标*/
                double d = alarmPointDistance - distanceMap.get(num - 1);
                GeoPoint aPoint = new GeoPoint(x0, y0, z0);
                GeoPoint bPoint = new GeoPoint(x1, y1, z1);
                GeoPoint geoPoint = caculateRawGeoPoint(aPoint, bPoint, d);
                double height = interpolateHeight(aPoint, bPoint, geoPoint);
                geoPoint.setAltitude(height);
                log.debug("计算结果:" + geoPoint);
                return geoPoint;
            }
            catch (Exception ex)
            {
                log.error("管线报警点坐标计算异常:"+ex.getMessage());
                return null;
            }
 
    }
 
    // 线性插值计算任意点的高度
    private static double interpolateHeight(GeoPoint startPoint, GeoPoint endPoint, GeoPoint alarmPoint) {
        double startX = startPoint.getLongitude();
        double startY = startPoint.getLatitude();
        double startZ = startPoint.getAltitude();
        double endX = endPoint.getLongitude();
        double endY = endPoint.getLatitude();
        double endZ = endPoint.getAltitude();
        // 目标点的坐标
        double targetX = alarmPoint.getLongitude();
        double targetY = alarmPoint.getLatitude();
        double distance = Math.sqrt(Math.pow(endX - startX, 2) + Math.pow(endY - startY, 2));
        double targetDistance = Math.sqrt(Math.pow(targetX - startX, 2) + Math.pow(targetY - startY, 2));
        double t = targetDistance / distance;
        double targetHeight = startZ + t * (endZ - startZ);
        return targetHeight;
    }
 
    /**
     * 已知WGS84坐标系 A 点,B点, X 在AB 弧线上, 且是最短的这条, AX距离已知,求X点坐标.
     *
     * @param aPoint
     * @param bPoint
     * @param distance_ax_in_meter
     * @return
     */
    private static GeoPoint caculateRawGeoPoint(GeoPoint aPoint, GeoPoint bPoint, double distance_ax_in_meter) {
        MyLatLng a = new MyLatLng(aPoint.getLongitude(), aPoint.getLatitude());
        MyLatLng b = new MyLatLng(bPoint.getLongitude(), bPoint.getLatitude());
        double angle = getAngle(a, b);
        //double angle = GisUtil.getNorthAngle(a.getM_Longitude(),a.getM_Latitude(), b.getM_Longitude(),b.getM_Latitude());
        MyLatLng x = getMyLatLng(a, distance_ax_in_meter / 1000.0, angle);
        GeoPoint xPoint = new GeoPoint(x.m_Longitude, x.m_Latitude, 0.0);
        return xPoint;
    }
 
    /**
     * 求B点经纬度
     *
     * @param A            已知点的经纬度,
     * @param distanceInKM AB两地的距离  单位km
     * @param angle        AB连线与正北方向的夹角(0~360)
     * @return B点的经纬度
     */
    private static MyLatLng getMyLatLng(MyLatLng A, double distanceInKM, double angle) {
 
        double dx = distanceInKM * 1000 * Math.sin(Math.toRadians(angle));
        double dy = distanceInKM * 1000 * Math.cos(Math.toRadians(angle));
 
        double bjd = (dx / A.Ed + A.m_RadLo) * 180. / Math.PI;
        double bwd = (dy / A.Ec + A.m_RadLa) * 180. / Math.PI;
        return new MyLatLng(bjd, bwd);
    }
 
    /**
     * 获取AB连线与正北方向的角度
     *
     * @param A A点的经纬度
     * @param B B点的经纬度
     * @return AB连线与正北方向的角度(0~360)
     */
    private static double getAngle(MyLatLng A, MyLatLng B) {
        double dx = (B.m_RadLo - A.m_RadLo) * A.Ed;
        double dy = (B.m_RadLa - A.m_RadLa) * A.Ec;
        double angle = 0.0;
        angle = Math.atan(Math.abs(dx / dy)) * 180. / Math.PI;
        double dLo = B.m_Longitude - A.m_Longitude;
        double dLa = B.m_Latitude - A.m_Latitude;
        if (dLo > 0 && dLa <= 0) {
            angle = (90. - angle) + 90;
        } else if (dLo <= 0 && dLa < 0) {
            angle = angle + 180.;
        } else if (dLo < 0 && dLa >= 0) {
            angle = (90. - angle) + 270;
        }
        return angle;
    }
 
    /**
     * 根据经纬度,计算两点间的距离
     *
     * @param GeoPoint pa 第一个点
     * @param GeoPoint  pb 第二个点
     * @return 返回距离 单位米
     */
    public static GeodeticCalculator geodeticCalculator = new GeodeticCalculator();
    public static double getDistance(GeoPoint pa, GeoPoint pb) {
        GlobalCoordinates source = new GlobalCoordinates(pa.getLatitude(), pa.getLongitude());
        GlobalCoordinates target = new GlobalCoordinates(pb.getLatitude(), pb.getLongitude());
        double distance = geodeticCalculator.calculateGeodeticCurve(Ellipsoid.WGS84, source, target).getEllipsoidalDistance();
        double res = Math.sqrt(Math.pow(pa.getAltitude() - pb.getAltitude(), 2) + Math.pow(distance, 2));
        return res;
    }
}