rain
2024-05-06 cbc15bffc95c486ec8fe67270d8d4e08de7b1407
Merge remote-tracking branch 'origin/ht-dev' into ht-dev
5 files modified
1 files added
266 ■■■■■ changed files
src/main/java/com/dji/sample/patches/service/impl/ShpToDataSourceServiceImpl.java 7 ●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/patches/utils/DistanceCalculator.java 7 ●●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/patches/utils/GeoToolsUtil.java 208 ●●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/patches/utils/PointPO.java 20 ●●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/patches/xml/mode/XMLTemplateModel.java 21 ●●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/territory/service/impl/TbDkjbxxServiceImpl.java 3 ●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/patches/service/impl/ShpToDataSourceServiceImpl.java
@@ -5,10 +5,7 @@
import com.dji.sample.patches.dao.ShpToDataSourceMapper;
import com.dji.sample.patches.model.entity.LotInfo;
import com.dji.sample.patches.service.ShpToDataSourceService;
import com.dji.sample.patches.utils.FormatConversionUtil;
import com.dji.sample.patches.utils.GeoToolsUtil;
import com.dji.sample.patches.utils.MultipartFileTOFileUtil;
import com.dji.sample.patches.utils.ShapeFileUtil;
import com.dji.sample.patches.utils.*;
import com.dji.sample.patches.xml.mode.XMLTemplateModel;
import com.dji.sample.patches.xml.utils.CreateWaylineFileUtils;
import com.dji.sample.territory.model.entity.TbDkjbxxEntity;
@@ -70,7 +67,7 @@
            lotInfo.setYzb(Double.valueOf(points[1]));
            shpToDataSourceMapper.insert(lotInfo);
        }
        Coordinate[] coordinates = GeoToolsUtil.getRoutePointOrder(list, airportLat, airportLon);
        List<PointPO> coordinates = GeoToolsUtil.getRoutePointOrder(list, airportLat, airportLon);
        XMLTemplateModel xmlModel = XMLTemplateModel.init(coordinates, list);
        CreateWaylineFileUtils.createWaylineFile(xmlModel, patchesConfigPojo.getTemplate(), patchesConfigPojo.getTargetTemplate(), patchesConfigPojo.getWaylines(), patchesConfigPojo.getTargetWaylines());
        // 压缩文件夹中的内容
src/main/java/com/dji/sample/patches/utils/DistanceCalculator.java
@@ -39,6 +39,13 @@
        return distance;
    }
    // 计算两点之间的欧几里得距离
    public static double distance(Coordinate a, Coordinate b) {
        double dx = a.getX() - b.getX();
        double dy = a.getY() - b.getY();
        return Math.sqrt(dx * dx + dy * dy);
    }
    /**
     *  中心点排序
     * @param coordinates 中心点数组
src/main/java/com/dji/sample/patches/utils/GeoToolsUtil.java
@@ -2,15 +2,15 @@
import com.dji.sample.patches.model.entity.LotInfo;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKTReader;
import org.locationtech.jts.operation.buffer.BufferOp;
import org.locationtech.jts.simplify.TopologyPreservingSimplifier;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
 * @PROJECT_NAME: drone
@@ -50,24 +50,85 @@
        return extremePoints;
    }
    public static Coordinate[] sortCoordinatesByNearestDistance(Coordinate[] coordinates) {
        // 将数组转换为List以便操作
        List<Coordinate> coordinateList = new ArrayList<>(Arrays.asList(coordinates));
        // 排序后的坐标列表
        List<Coordinate> sortedCoordinates = new ArrayList<>();
        // 如果列表不为空,开始排序
        if (!coordinateList.isEmpty()) {
            // 将第一个点添加到排序列表中
            sortedCoordinates.add(coordinateList.remove(0));
            // 循环处理剩余的点
            while (!coordinateList.isEmpty()) {
                double minDistance = Double.MAX_VALUE;
                Coordinate nearest = null;
                // 查找距离排序列表中最后一个点最近的点
                for (Coordinate c : coordinateList) {
                    double distance = DistanceCalculator.distance(sortedCoordinates.get(sortedCoordinates.size() - 1), c);
                    if (distance < minDistance) {
                        minDistance = distance;
                        nearest = c;
                    }
                }
                // 将找到的最近的点添加到排序列表中,并从原始列表中移除它
                sortedCoordinates.add(nearest);
                coordinateList.remove(nearest);
            }
        }
        return sortedCoordinates.toArray(new Coordinate[0]);
    }
    /**
     * 获取拐点坐标(替换上面获取四个航点坐标方法)
     *
     * @return
     */
    public static List<Coordinate> getSimplifyPolygons(Geometry polygon) {
    public static List<Coordinate> getSimplifyPolygons(Geometry originalPolygon) {
        // 使用 TopologyPreservingSimplifier 进行抽稀
        double distanceTolerance = 1.0; // 设置抽稀的容忍度,根据实际需要调整
        Geometry simplifiedPolygon = TopologyPreservingSimplifier.simplify(polygon, distanceTolerance);
        List coordinatesList = new ArrayList();
        // 获取简化后的多边形的拐点
        List<Coordinate> coordinatesList = new ArrayList<>();
        for (int i = 0; i < simplifiedPolygon.getNumPoints(); i++) {
            coordinatesList.add(simplifiedPolygon.getCoordinate());
        // 应用抽稀算法,这里使用TopologyPreservingSimplifier作为示例
        double distanceTolerance = 100.0; // 抽稀的容忍度,根据需要调整
        Geometry simplifiedGeometry = TopologyPreservingSimplifier.simplify(originalPolygon, distanceTolerance);
        // 转换回Polygon类型(如果需要)
        Polygon simplifiedPolygon = (Polygon) simplifiedGeometry;
        // 获取简化后的多边形的坐标序列
        Coordinate[] coordinates = simplifiedPolygon.getCoordinates();
        // 使用自定义Comparator对数组进行排序
//        Arrays.sort(coordinates, Comparator.comparing(Coordinate::getX).thenComparing(Coordinate::getY));
        // 假设第一个点是起始点
//        Coordinate startPoint = coordinates[0];
//
//        // 使用自定义Comparator对数组进行排序,根据与startPoint的距离升序排序
//        Arrays.sort(coordinates, Comparator.comparingDouble(c -> DistanceCalculator.distance(startPoint, c)));
        Coordinate[] newCoord = sortCoordinatesByNearestDistance(coordinates);
        // 遍历坐标数组,打印每个坐标点
        for (Coordinate coord : newCoord) {
            coordinatesList.add(coord);
        }
        return coordinatesList;
        // 使用Set去除重复项
        Set<Coordinate> set = new HashSet<>(coordinatesList);
        // 将Set转回List
        List<Coordinate> uniqueCoordinates = new ArrayList<>(set);
        return uniqueCoordinates;
    }
    public static int getSimplifyPolygonsNum(Geometry polygon) {
@@ -78,64 +139,64 @@
        return simplifiedPolygon.getNumPoints();
    }
//    public static void main(String[] args) {
//        //测试
//        List<LotInfo> list = new ArrayList<>();
//        list.add(LotInfo.builder().dkfw("POLYGON((115.866465564947 28.6344502965542, 115.86425430209 28.6357383285408, 115.864551734716 28.633120921433, 115.866977149064 28.6338435339976, 115.866465564947 28.6344502965542))").build());
//        list.add(LotInfo.builder().dkfw("POLYGON((115.864006690605 28.6202713913694, 115.86002109342 28.6162025130492, 115.866374254306 28.6142037658042, 115.865912044006 28.6172001020759, 115.864006690605 28.6202713913694))").build());
//        list.add(LotInfo.builder().dkfw("POLYGON((115.839366933455 28.6161999317332, 115.841288489469 28.6160843601496, 115.840931570318 28.6181544912247, 115.838147600941 28.618654178036, 115.839366933455 28.6161999317332))").build());
//        list.add(LotInfo.builder().dkfw("POLYGON((115.857499052697 28.6784702230642, 115.859109158101 28.6762273976226, 115.863677723232 28.6766081113836, 115.862154868188 28.6790827508297, 115.857499052697 28.6784702230642))").build());
//        list.add(LotInfo.builder().dkfw("POLYGON((115.834974056705 28.6659171428962, 115.833760531592 28.6634960413229, 115.832422084777 28.6624550271329, 115.829745191145 28.6631986086972, 115.831232354274 28.6608191476914, 115.833314382654 28.6603729987527, 115.835545127347 28.6618601618814, 115.837032290475 28.6639421902615, 115.834974056705 28.6659171428962))").build());
//        list.add(LotInfo.builder().dkfw("POLYGON((115.885622116006 28.5766308429787, 115.883936664461 28.5771582901683, 115.883365593819 28.5752547213636, 115.883555950699 28.5740174016407, 115.88365112914 28.5724945465969, 115.885364341064 28.5721138328361, 115.886696839227 28.5725897250371, 115.887458266749 28.5736366878797, 115.886792017668 28.5753498998039, 115.885622116006 28.5766308429787))").build());
//        list.add(LotInfo.builder().dkfw("POLYGON((115.857644341395 28.5750890964568, 115.857572957565 28.5729475815515, 115.858429563527 28.5728761977213, 115.859072017998 28.5738041875136, 115.859072017998 28.5748035611361, 115.857644341395 28.5750890964568))").build());
//        list.add(LotInfo.builder().dkfw("POLYGON((115.912181587649 28.6231542087745, 115.912181587649 28.6215123806805, 115.915893546818 28.6212268453598, 115.916036314478 28.6231542087745, 115.912181587649 28.6231542087745))").build());
//        list.add(LotInfo.builder().dkfw("POLYGON((115.842039042965 28.6314426646115, 115.840992080122 28.631252307731, 115.842324578286 28.6305860586493, 115.843181184248 28.6305860586493, 115.84403779021 28.6304908802091, 115.84394261177 28.6317281999322, 115.842039042965 28.6314426646115))").build());
//        list.add(LotInfo.builder().dkfw("POLYGON((115.807011889796 28.623935465138, 115.805869748513 28.6224126100944, 115.810247956764 28.6220318963334, 115.809581707682 28.623935465138, 115.807011889796 28.623935465138))").build());
    public static void main(String[] args) {
        //测试
        List<LotInfo> list = new ArrayList<>();
        list.add(LotInfo.builder().dkfw("POLYGON((115.866465564947 28.6344502965542, 115.86425430209 28.6357383285408, 115.864551734716 28.633120921433, 115.866977149064 28.6338435339976, 115.866465564947 28.6344502965542))").build());
        list.add(LotInfo.builder().dkfw("POLYGON((115.864006690605 28.6202713913694, 115.86002109342 28.6162025130492, 115.866374254306 28.6142037658042, 115.865912044006 28.6172001020759, 115.864006690605 28.6202713913694))").build());
        list.add(LotInfo.builder().dkfw("POLYGON((115.839366933455 28.6161999317332, 115.841288489469 28.6160843601496, 115.840931570318 28.6181544912247, 115.838147600941 28.618654178036, 115.839366933455 28.6161999317332))").build());
        list.add(LotInfo.builder().dkfw("POLYGON((115.857499052697 28.6784702230642, 115.859109158101 28.6762273976226, 115.863677723232 28.6766081113836, 115.862154868188 28.6790827508297, 115.857499052697 28.6784702230642))").build());
        list.add(LotInfo.builder().dkfw("POLYGON((115.834974056705 28.6659171428962, 115.833760531592 28.6634960413229, 115.832422084777 28.6624550271329, 115.829745191145 28.6631986086972, 115.831232354274 28.6608191476914, 115.833314382654 28.6603729987527, 115.835545127347 28.6618601618814, 115.837032290475 28.6639421902615, 115.834974056705 28.6659171428962))").build());
        list.add(LotInfo.builder().dkfw("POLYGON((115.885622116006 28.5766308429787, 115.883936664461 28.5771582901683, 115.883365593819 28.5752547213636, 115.883555950699 28.5740174016407, 115.88365112914 28.5724945465969, 115.885364341064 28.5721138328361, 115.886696839227 28.5725897250371, 115.887458266749 28.5736366878797, 115.886792017668 28.5753498998039, 115.885622116006 28.5766308429787))").build());
        list.add(LotInfo.builder().dkfw("POLYGON((115.857644341395 28.5750890964568, 115.857572957565 28.5729475815515, 115.858429563527 28.5728761977213, 115.859072017998 28.5738041875136, 115.859072017998 28.5748035611361, 115.857644341395 28.5750890964568))").build());
        list.add(LotInfo.builder().dkfw("POLYGON((115.912181587649 28.6231542087745, 115.912181587649 28.6215123806805, 115.915893546818 28.6212268453598, 115.916036314478 28.6231542087745, 115.912181587649 28.6231542087745))").build());
        list.add(LotInfo.builder().dkfw("POLYGON((115.842039042965 28.6314426646115, 115.840992080122 28.631252307731, 115.842324578286 28.6305860586493, 115.843181184248 28.6305860586493, 115.84403779021 28.6304908802091, 115.84394261177 28.6317281999322, 115.842039042965 28.6314426646115))").build());
        list.add(LotInfo.builder().dkfw("POLYGON((115.807011889796 28.623935465138, 115.805869748513 28.6224126100944, 115.810247956764 28.6220318963334, 115.809581707682 28.623935465138, 115.807011889796 28.623935465138))").build());
//        list.forEach(patche -> {
//            String wkt = patche.getDkfw();
//            // 解析WKT字符串为多边形
//            WKTReader wktReader = new WKTReader(JTSFactoryFinder.getGeometryFactory());
//            Geometry polygon = null;
//            try {
//                polygon = wktReader.read(wkt);
//            } catch (ParseException e) {
//                throw new RuntimeException(e);
//            }
//
//            // 开始封装中心点坐标
//            Coordinate coordinateCentro = getCentro(polygon);
//
//            // 开始封装图斑4个航线
////            List<Coordinate> coordinatePointList = getExtremePoints(polygon);
//            List<Coordinate> coordinatePointList = getSimplifyPolygons(polygon);
//
//
////        list.forEach(patche -> {
////            String wkt = patche.getDkfw();
////            // 解析WKT字符串为多边形
////            WKTReader wktReader = new WKTReader(JTSFactoryFinder.getGeometryFactory());
////            Geometry polygon = null;
////            try {
////                polygon = wktReader.read(wkt);
////            } catch (ParseException e) {
////                throw new RuntimeException(e);
////            }
////
////            // 开始封装中心点坐标
////            Coordinate coordinateCentro = getCentro(polygon);
////
////            // 开始封装图斑4个航线
//////            List<Coordinate> coordinatePointList = getExtremePoints(polygon);
////            List<Coordinate> coordinatePointList = getSimplifyPolygons(polygon);
////
////
////        });
//
//
//        Coordinate[] ret = getRoutePointOrder(list,28.624514734, 115.856725497);
//
//        for (Coordinate c :
//                ret) {
//            System.out.println(c);
//        }
//
//
//    }
//        });
        List<PointPO> pointPOS = getRoutePointOrder(list, 28.624514734, 115.856725497);
        for (PointPO c :
                pointPOS) {
            System.out.println(c);
        }
    }
    /**
     * 航线点排序
     *
     * @return
     */
    public static Coordinate[] getRoutePointOrder(List<LotInfo> list, double airportLat, double airportLon) {
    public static List<PointPO> getRoutePointOrder(List<LotInfo> list, double airportLat, double airportLon) {
        List<Coordinate> centros = new ArrayList<>();
        List<List<Coordinate>> extremePoints = new ArrayList<>();
        Map<Coordinate, List<Coordinate>> points = new HashMap<>();
        AtomicInteger numSize = new AtomicInteger();
        list.forEach(patche -> {
        for (LotInfo patche : list) {
            String wkt = patche.getDkfw();
            // 解析WKT字符串为多边形
            WKTReader wktReader = new WKTReader(JTSFactoryFinder.getGeometryFactory());
@@ -148,6 +209,13 @@
            // 开始封装中心点坐标
            Coordinate coordinateCentro = getCentro(polygon);
            double distance = DistanceCalculator.calculateDistance(airportLat, airportLon, coordinateCentro.y,coordinateCentro.x);
            // 机场范围,操作机场范围将不生成
            if (distance * 1000 > 7000) {
                continue;
            }
            centros.add(coordinateCentro);
            // 开始封装图斑4个航线
@@ -157,9 +225,9 @@
//            points.put(coordinateCentro, coordinatePointList);
            // 保存稀释拐点之后总数量
            numSize.set(numSize.get() + getSimplifyPolygonsNum(polygon));
            numSize.set(numSize.get() + coordinatePointList.size());
        }
        });
        // 开始排序
        Coordinate[] coordinates = new Coordinate[centros.size() + 1];
@@ -201,38 +269,42 @@
        Coordinate[] retCoordinate = new Coordinate[coordinateList.size()];
        List<Coordinate> oldCoordinateList = new ArrayList<>(coordinateList);
        // 获取中心点
        Coordinate[] sortedCoordinates = DistanceCalculator.sortByDistance(coordinateList, airportLat, airportLon, 0, retCoordinate);
        // 开始拼接图斑点位--按中心坐标数组排序顺序
        Coordinate[] retc = new Coordinate[numSize.get() + 1];
        List<PointPO> retcList = new ArrayList<>();
        // 赋值起点
        retc[0] = sortedCoordinates[0];
        retcList.add(PointPO.builder().index(0).coordinate(sortedCoordinates[0]).build());
        List<Integer> indexs = new ArrayList<>();
        // 拿排序前的索引index 根据排序前和排序后的结果匹对------》后期优化
        for (int i = 1; i<sortedCoordinates.length; i++) {
        for (int i = 1; i < sortedCoordinates.length; i++) {
            Coordinate c1 = sortedCoordinates[i];
            for (int j = 1; j < oldCoordinateList.size(); j++) {
                Coordinate c2 = oldCoordinateList.get(j);
                if (c1.getX() == c2.getX() && c1.getY() == c2.getY()) {
                    indexs.add(j-1);
                    indexs.add(j - 1);
                }
            }
        }
        // 根据排序前的索引按顺序赋值
        int i = 0;
        for (Integer index: indexs) {
            for (Coordinate coordinate:extremePoints.get(index)) {
                i = i+1;
        for (Integer index : indexs) {
            for (Coordinate coordinate : extremePoints.get(index)) {
                i = i + 1;
                retc[i] = coordinate;
                retcList.add(PointPO.builder().index(index).coordinate(coordinate).build());
            }
        }
        return retc;
        return retcList;
    }
src/main/java/com/dji/sample/patches/utils/PointPO.java
New file
@@ -0,0 +1,20 @@
package com.dji.sample.patches.utils;
import lombok.Builder;
import lombok.Data;
import org.locationtech.jts.geom.Coordinate;
/**
 * @PROJECT_NAME: drone
 * @DESCRIPTION:
 * @USER: aix
 * @DATE: 2024/5/6 10:41
 */
@Data
@Builder
public class PointPO {
    private int index;
    private Coordinate coordinate;
}
src/main/java/com/dji/sample/patches/xml/mode/XMLTemplateModel.java
@@ -2,6 +2,7 @@
import com.dji.sample.patches.model.entity.LotInfo;
import com.dji.sample.patches.utils.GeoToolsUtil;
import com.dji.sample.patches.utils.PointPO;
import com.dji.sample.patches.xml.mode.share.ActionGroup;
import com.dji.sample.patches.xml.mode.share.ActionMode;
import com.dji.sample.patches.xml.mode.share.ActionTrigger;
@@ -46,14 +47,15 @@
     * @param lotInfos
     * @return
     */
    public static XMLTemplateModel init(Coordinate[] coordinates,List<LotInfo> lotInfos) {
    public static XMLTemplateModel init(List<PointPO> coordinates, List<LotInfo> lotInfos) {
        Folder folder = FolderUtils.setFloder();
        List<Placemark> placemarkList = new ArrayList<>();
        int i = 0;
        for (Coordinate c:coordinates) {
        for (PointPO pointPO:coordinates) {
            if (i != 0) {//去除第一个航点
                Coordinate c = pointPO.getCoordinate();
                Placemark placemark = PlacemarkUtils.setPlacemark(c.x + "," + c.y);
                // 增加事件组
@@ -70,16 +72,11 @@
                ActionMode actionMode = new ActionMode();
                actionMode.setActionId(0);
                actionMode.setActionActuatorFunc(CameraActionEnum.TAKE_PHOTO.getDescription());//拍照事件
                // 计算获取图斑编号
                int quotient = i / 4;
                if (i % 4 != 0) { // 检查是否有余数
                    quotient++; // 如果有余数,商加1
                }
                if (quotient == 0) quotient = 1;
//                actionMode.setActionActuatorFuncParam(ActionUtils.setTakePhoto(lotInfos.get(quotient-1).getDkbh()));
                actionMode.setActionActuatorFuncParam(ActionUtils.setTakePhoto("测试"));
                // 设置媒体文件名称后缀
                actionMode.setActionActuatorFuncParam(ActionUtils.setTakePhoto(lotInfos.get(pointPO.getIndex()).getDkbh()));
//                actionMode.setActionActuatorFuncParam(ActionUtils.setTakePhoto("测试"));
                list.add(actionMode);
                ActionMode actionMode2 = new ActionMode();
@@ -103,7 +100,7 @@
                .author("Aix")
                .createTime(String.valueOf(System.currentTimeMillis()))
                .updateTime(String.valueOf(System.currentTimeMillis()))
                .missionConfig(MissionConfigUtils.setMissionConfig(coordinates[0].y + "," + coordinates[0].x + ",0"))
                .missionConfig(MissionConfigUtils.setMissionConfig(coordinates.get(0).getCoordinate().y + "," + coordinates.get(0).getCoordinate().x + ",0"))
                .folder(folder)
                .build();
@@ -129,7 +126,7 @@
        double airportLat = 28.624514734; // 机场纬度
        double airportLon = 115.856725497; // 机场经度
        // 解析图斑生成航点,按顺序返回
        Coordinate[] coordinates = GeoToolsUtil.getRoutePointOrder(list, airportLat, airportLon);
        List<PointPO> coordinates = GeoToolsUtil.getRoutePointOrder(list, airportLat, airportLon);
        // 初始化模板对象
        XMLTemplateModel xmlModel = XMLTemplateModel.init(coordinates, list);
src/main/java/com/dji/sample/territory/service/impl/TbDkjbxxServiceImpl.java
@@ -8,6 +8,7 @@
import com.dji.sample.patches.model.entity.LotInfo;
import com.dji.sample.patches.utils.GeoToolsUtil;
import com.dji.sample.patches.utils.MultipartFileTOFileUtil;
import com.dji.sample.patches.utils.PointPO;
import com.dji.sample.patches.xml.mode.XMLTemplateModel;
import com.dji.sample.patches.xml.utils.CreateWaylineFileUtils;
import com.dji.sample.territory.dao.ITbDkjbxxMapper;
@@ -104,7 +105,7 @@
    public MultipartFile listFile(String workspaceId, String waylineName, double airportLat, double airportLon) throws IOException {
        List<TbDkjbxxEntity> list = iTbDkjbxxMapper.selectList(null);
        List<LotInfo> info = dbConvertToEntity(list);
        Coordinate[] coordinates = GeoToolsUtil.getRoutePointOrder(info, airportLat, airportLon);
        List<PointPO> coordinates = GeoToolsUtil.getRoutePointOrder(info, airportLat, airportLon);
        // 创建XML模板模型
        XMLTemplateModel xmlModel = XMLTemplateModel.init(coordinates, info);
        CreateWaylineFileUtils.createWaylineFile(xmlModel, patchesConfigPojo.getTemplate(), patchesConfigPojo.getTargetTemplate(), patchesConfigPojo.getWaylines(), patchesConfigPojo.getTargetWaylines());