‘liusuyi’
2023-06-07 27fa371d0fff1590be0534277fe8680ed6515315
增加管线泄露报警点坐标算法
已添加5个文件
346 ■■■■■ 文件已修改
ard-work/src/main/java/com/ruoyi/alarm/tubeAlarm/service/impl/GeoPoint.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/alarm/tubeAlarm/service/impl/LeakPointCalculation.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/alarm/tubeAlarm/service/impl/MyLatLng.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/alarm/tubeAlarm/service/impl/Point3D.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/alarm/tubeAlarm/service/impl/testService.java 220 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/alarm/tubeAlarm/service/impl/GeoPoint.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.ruoyi.alarm.tubeAlarm.service.impl;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
 * @ClassName GeoPoint
 * @Description:
 * @Author åˆ˜è‹ä¹‰
 * @Date 2023/6/6 20:22
 * @Version 1.0
 */
@Data
@AllArgsConstructor
public class GeoPoint {
    Double longitude;
    Double latitude;
}
ard-work/src/main/java/com/ruoyi/alarm/tubeAlarm/service/impl/LeakPointCalculation.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,50 @@
package com.ruoyi.alarm.tubeAlarm.service.impl;
import java.util.ArrayList;
import java.util.List;
public class LeakPointCalculation {
    public static void main(String[] args) {
        // å‡è®¾æœ‰ä¸‰æ®µç®¡çº¿
        List<Point3D> pipeline = new ArrayList<>();
        pipeline.add(new Point3D(124.925198285, 46.68693001, 147.5));     // ç¬¬ä¸€æ®µç®¡çº¿çš„起点坐标
        pipeline.add(new Point3D(124.925490653, 46.687071291, 148.2));  // ç¬¬ä¸€æ®µç®¡çº¿çš„终点坐标和高程
        pipeline.add(new Point3D(124.926401943, 46.686812672, 143.5));  // ç¬¬äºŒæ®µç®¡çº¿çš„终点坐标和高程
        pipeline.add(new Point3D(124.926981879, 46.686644854, 147.4));  // ç¬¬ä¸‰æ®µç®¡çº¿çš„终点坐标和高程
        double leakPointDistance = 100.0;  // æ³„漏点相对于管线起点的长度
        // 1. ç¡®å®šæ³„漏点所在的管线段
        Point3D startPoint = null;
        Point3D endPoint = null;
        double accumulatedLength = 0.0;
        for (int i = 0; i < pipeline.size() - 1; i++) {
            startPoint = pipeline.get(i);
            endPoint = pipeline.get(i + 1);
            double segmentLength = calculateDistance(startPoint, endPoint);
            accumulatedLength += segmentLength;
            if (accumulatedLength >= leakPointDistance) {
                break;
            }
        }
        // 2. è®¡ç®—泄漏点在所在管线段上的相对位置
        double relativePosition = (accumulatedLength - leakPointDistance) / calculateDistance(startPoint, endPoint);
        // 3. è®¡ç®—泄漏点的坐标
        double x = startPoint.getX() + (endPoint.getX() - startPoint.getX()) * relativePosition;
        double y = startPoint.getY() + (endPoint.getY() - startPoint.getY()) * relativePosition;
        double z = startPoint.getZ() + (endPoint.getZ() - startPoint.getZ()) * relativePosition;
        Point3D leakPoint = new Point3D(x, y, z);
        System.out.println("泄漏点坐标:" + leakPoint);
    }
    // è®¡ç®—两个点之间的距离
    private static double calculateDistance(Point3D point1, Point3D point2) {
        double dx = point2.getX() - point1.getX();
        double dy = point2.getY() - point1.getY();
        double dz = point2.getZ() - point1.getZ();
        return Math.sqrt(dx * dx + dy * dy + dz * dz);
    }
}
ard-work/src/main/java/com/ruoyi/alarm/tubeAlarm/service/impl/MyLatLng.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,39 @@
package com.ruoyi.alarm.tubeAlarm.service.impl;
import lombok.Data;
/**
 * @ClassName MyLatLng
 * @Description:
 * @Author åˆ˜è‹ä¹‰
 * @Date 2023/6/6 20:14
 * @Version 1.0
 */
@Data
public class MyLatLng {
    final static double Rc = 6378137;
    final static double Rj = 6356725;
    double m_LoDeg, m_LoMin, m_LoSec;
    double m_LaDeg, m_LaMin, m_LaSec;
    double m_Longitude, m_Latitude;
    double m_RadLo, m_RadLa;
    double Ec;
    double Ed;
    public MyLatLng(double longitude, double latitude) {
        m_LoDeg = (int) longitude;
        m_LoMin = (int) ((longitude - m_LoDeg) * 60);
        m_LoSec = (longitude - m_LoDeg - m_LoMin / 60.) * 3600;
        m_LaDeg = (int) latitude;
        m_LaMin = (int) ((latitude - m_LaDeg) * 60);
        m_LaSec = (latitude - m_LaDeg - m_LaMin / 60.) * 3600;
        m_Longitude = longitude;
        m_Latitude = latitude;
        m_RadLo = longitude * Math.PI / 180.;
        m_RadLa = latitude * Math.PI / 180.;
        Ec = Rj + (Rc - Rj) * (90. - m_Latitude) / 90.;
        Ed = Ec * Math.cos(m_RadLa);
    }
}
ard-work/src/main/java/com/ruoyi/alarm/tubeAlarm/service/impl/Point3D.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
package com.ruoyi.alarm.tubeAlarm.service.impl;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
 * @Description:
 * @ClassName: Point3D
 * @Author: åˆ˜è‹ä¹‰
 * @Date: 2023å¹´06月07日15:12
 * @Version: 1.0
 **/
@Data
@AllArgsConstructor
public class Point3D {
    private double x;
    private double y;
    private double z;
}
ard-work/src/main/java/com/ruoyi/alarm/tubeAlarm/service/impl/testService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,220 @@
package com.ruoyi.alarm.tubeAlarm.service.impl;
import com.ruoyi.alarmpoints.tube.domain.ArdTubesDetails;
import com.ruoyi.alarmpoints.tube.mapper.ArdTubesDetailsMapper;
import com.ruoyi.device.hiksdk.util.hikSdkUtil.GisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.List;
/**
 * @Description:
 * @ClassName: testService
 * @Author: åˆ˜è‹ä¹‰
 * @Date: 2023å¹´06月06日15:20
 * @Version: 1.0
 **/
@Service
@Slf4j
public class testService {
    @Resource
    ArdTubesDetailsMapper ardTubesDetailsMapper;
    // è®¡ç®—两个点之间的距离
    public static double calculateDistance(double x1, double y1, double z1, double x2, double y2, double z2) {
        double deltaX = x2 - x1;
        double deltaY = y2 - y1;
        double deltaZ = z2 - z1;
        double distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ);
        return distance;
    }
    @PostConstruct
    public void getlist() {
        Integer alarmPointDistance = 100;
        ArdTubesDetails atd = new ArdTubesDetails();
        atd.setReelNumber("10");
        List<ArdTubesDetails> ardTubesDetails = ardTubesDetailsMapper.selectArdTubesDetailsList(atd);
        TreeMap<Integer, Double> distanceMap = new TreeMap<>();
        // åˆ›å»ºè‡ªå®šä¹‰çš„Comparator对象,按照InflectionPointNumber字段进行排序
        Comparator<ArdTubesDetails> comparator = Comparator.comparingInt(person -> Integer.parseInt(person.getInflectionPointNumber()));
        // ä½¿ç”¨Collections.sort方法进行排序
        Collections.sort(ardTubesDetails, comparator);
        /*起点坐标*/
        Double x = ardTubesDetails.get(0).getLongitude();
        Double y = ardTubesDetails.get(0).getLatitude();
        TreeMap<Integer, Object> pointMap = new TreeMap<>();
        Double tempX = x;
        Double tempY = y;
        Double tempD = 0.0;
        for (ArdTubesDetails ardtd : ardTubesDetails) {
            double distance = GisUtil.getDistance(tempX, tempY, ardtd.getLongitude(), ardtd.getLatitude());
            tempD += distance;
            distanceMap.put(Integer.parseInt(ardtd.getInflectionPointNumber()), tempD);
            pointMap.put(Integer.parseInt(ardtd.getInflectionPointNumber()), ardtd);
            tempX = ardtd.getLongitude();
            tempY = ardtd.getLatitude();
        }
        /*按顺序比对距离,找到该距离属于哪个拐点之后*/
        int num = 1;//拐点序号
        Double distanceDiff = 0.0;//与拐点距离差
        Double distanceA = 0.0;
        Double distanceB = 0.0;
        while (distanceB < alarmPointDistance) {
            num++;
            distanceA = distanceMap.get(num-1);
            distanceB = distanceMap.get(num);
        }
        log.info("报警点在拐点" + (num - 1) + "与" + (num) + "之间");
        /*获取当前报警点所在的2个拐点的坐标*/
        ArdTubesDetails point1 = (ArdTubesDetails) pointMap.get(num - 1);
        double x0 = point1.getLongitude();
        double y0 = point1.getLatitude();
        double z0 = point1.getAltitude();
        ArdTubesDetails point2 = (ArdTubesDetails) pointMap.get(num);
        double x1 = point2.getLongitude();
        double y1 = point2.getLatitude();
        double z1 = point2.getAltitude();
        /*计算报警点坐标*/
        double ABdistance = GisUtil.getDistance(x0, y0, x1, y1);
        double Bdistance = z1 > z0 ? z1 - z0 : z0 - z1;
        double angleC = Math.atan(Bdistance / ABdistance);
        log.info("对边与邻边对应角的弧度:" + angleC + " åº¦");
        // å°†å¼§åº¦è½¬æ¢ä¸ºè§’度
        double angleDeg = Math.toDegrees(angleC);
        log.info("对边与邻边对应角的角度:" + angleDeg + " åº¦");
        /*报警所在的2个拐点,起点高于终端*/
        if(z0>z1)
        {
            distanceDiff = alarmPointDistance - distanceA;
            GeoPoint aPoint = new GeoPoint(x0, y0);
            GeoPoint bPoint = new GeoPoint(x1, y1);
            double sp = Math.sin(angleC) * distanceDiff;
            log.info("水平距离:" + sp + " ç±³");
            GeoPoint geoPoint = caculateRawGeoPoint(aPoint, bPoint, sp);
            log.info(geoPoint.toString());
            /*计算高层*/
            double ACdistance = GisUtil.getDistance(geoPoint.getLongitude(), geoPoint.getLatitude(),x1, y1);
            // æ±‚解斜边的长度
            double hypotenuse = ACdistance * Math.tan(angleC) + z1;
            log.info("C点高层:" + hypotenuse + " ç±³");
        }
        else
        {
            distanceDiff = alarmPointDistance - distanceA;
            GeoPoint aPoint = new GeoPoint(x0, y0);
            GeoPoint bPoint = new GeoPoint(x1, y1);
            double sp = Math.sin(angleC) * distanceDiff;
            log.info("水平距离:" + sp + " ç±³");
            GeoPoint geoPoint = caculateRawGeoPoint(aPoint, bPoint, sp);
            log.info(geoPoint.toString());
            /*计算高层*/
            double ACdistance = GisUtil.getDistance(x0, y0, geoPoint.getLongitude(), geoPoint.getLatitude());
            // æ±‚解斜边的长度
            double hypotenuse = ACdistance * Math.tan(angleC) + z0;
            log.info("C点高层:" + hypotenuse + " ç±³");
        }
    }
    //判断2个线段的斜率
    public static void main(String[] args) {
        // å‡è®¾ç»™å®šçš„三个坐标点 A、B、C
        double x1 = 124.925490653;
        double y1 = 46.687071291;
        double x2 = 124.9255455011709;
        double y2 = 46.68705572539618;
        double x3 = 124.926401943;
        double y3 = 46.686812672;
        // è®¡ç®—斜率
        double slope1 = (y2 - y1) / (x2 - x1);
        double slope2 = (y3 - y2) / (x3 - x2);
        // è®¾ç½®æ–œçŽ‡å·®å€¼çš„é˜ˆå€¼
        double threshold = 0.0000001;
        // æ£€æŸ¥æ–œçŽ‡æ˜¯å¦ç›¸ç­‰
        if (Math.abs(slope1 - slope2) < threshold) {
            log.info("这三个点共线");
        } else {
            log.info("这三个点不共线");
        }
    }
    /**
     * å·²çŸ¥WGS84坐标系 A ç‚¹ï¼ŒB点, X åœ¨AB å¼§çº¿ä¸Š, ä¸”是最短的这条, AX距离已知,求X点坐标.
     *
     * @param aPoint
     * @param bPoint
     * @param distance_ax_in_meter
     * @return
     */
    public 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); //getAngle(a,x)==getAngle(a,b)
        MyLatLng x = getMyLatLng(a, distance_ax_in_meter / 1000.0, angle);
        GeoPoint xPoint = new GeoPoint(x.m_Longitude, x.m_Latitude);
        return xPoint;
    }
    public static GeoPoint caculateRawGeoPoint1(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);
        MyLatLng x = getMyLatLng(a, (360-distance_ax_in_meter) / 1000.0, angle);
        GeoPoint xPoint = new GeoPoint(x.m_Longitude, x.m_Latitude);
        return xPoint;
    }
    /**
     * æ±‚B点经纬度
     *
     * @param A            å·²çŸ¥ç‚¹çš„经纬度,
     * @param distanceInKM AB两地的距离  å•位km
     * @param angle        AB连线与正北方向的夹角(0~360)
     * @return B点的经纬度
     */
    public 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)
     */
    public 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;
    }
}