| | |
| | | |
| | | 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 |
| | |
| | | return extremePoints; |
| | | } |
| | | |
| | | /** |
| | | * 航线点排序 |
| | | * |
| | | * @return |
| | | */ |
| | | public static Coordinate [] getRoutePointOrder(List<LotInfo> list) { |
| | | List<Coordinate> centros = new ArrayList<>(); |
| | | List<List<Coordinate>> extremePoints = new ArrayList<>(); |
| | | Map<Coordinate,List<Coordinate>> points = new HashMap<>(); |
| | | 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); |
| | | } |
| | | public static Coordinate[] sortCoordinatesByNearestDistance(Coordinate[] coordinates) { |
| | | |
| | | // 开始封装中心点坐标 |
| | | Coordinate coordinateCentro = getCentro(polygon); |
| | | centros.add(coordinateCentro); |
| | | // 将数组转换为List以便操作 |
| | | List<Coordinate> coordinateList = new ArrayList<>(Arrays.asList(coordinates)); |
| | | |
| | | // 开始封装图斑4个航线 |
| | | List<Coordinate> coordinatePointList = getExtremePoints(polygon); |
| | | extremePoints.add(coordinatePointList); |
| | | points.put(coordinateCentro,coordinatePointList); |
| | | // 排序后的坐标列表 |
| | | List<Coordinate> sortedCoordinates = new ArrayList<>(); |
| | | |
| | | }); |
| | | // 如果列表不为空,开始排序 |
| | | if (!coordinateList.isEmpty()) { |
| | | // 将第一个点添加到排序列表中 |
| | | sortedCoordinates.add(coordinateList.remove(0)); |
| | | |
| | | // 开始排序 |
| | | // 机场经纬度 |
| | | double airportLat = 28.624514734; // 机场纬度 |
| | | double airportLon = 115.856725497; // 机场经度 |
| | | Coordinate [] coordinates = new Coordinate[centros.size() + 1]; |
| | | List<Coordinate> coordinateList = new ArrayList<>(); |
| | | coordinates[0] = new Coordinate(airportLon, airportLat); //第一个为机场经纬度 |
| | | coordinateList.add(new Coordinate(airportLon, airportLat)); //第一个为机场经纬度) |
| | | for (int i = 1; i < centros.size() + 1; i++) { |
| | | coordinates[i] = centros.get(i-1); |
| | | coordinateList.add(centros.get(i-1)); |
| | | } |
| | | // 循环处理剩余的点 |
| | | while (!coordinateList.isEmpty()) { |
| | | double minDistance = Double.MAX_VALUE; |
| | | Coordinate nearest = null; |
| | | |
| | | // 对中心坐标数组进行排序 |
| | | Coordinate[] retCoordinate = new Coordinate[coordinateList.size()]; |
| | | Coordinate[] sortedCoordinates = DistanceCalculator.sortByDistance(coordinateList, airportLat, airportLon, 0,retCoordinate); |
| | | |
| | | // 开始拼接图斑点位--按中心坐标数组排序顺序 |
| | | // 长度-3第一个起点只有一个点位 |
| | | Coordinate[] retc = new Coordinate[sortedCoordinates.length * 4 - 3]; |
| | | // 赋值起点 |
| | | retc[0] = sortedCoordinates[0]; |
| | | int i = 0; |
| | | for (Coordinate num : sortedCoordinates) { |
| | | List<Coordinate> coordinatePoints = points.get(num); |
| | | if (null != coordinatePoints) { |
| | | for (int j = 0; j < coordinatePoints.size(); j++) { |
| | | // 开始拼接 |
| | | retc[i * coordinatePoints.size() + j - 3] = coordinatePoints.get(j); |
| | | // 查找距离排序列表中最后一个点最近的点 |
| | | for (Coordinate c : coordinateList) { |
| | | double distance = DistanceCalculator.distance(sortedCoordinates.get(sortedCoordinates.size() - 1), c); |
| | | if (distance < minDistance) { |
| | | minDistance = distance; |
| | | nearest = c; |
| | | } |
| | | } |
| | | } |
| | | |
| | | i++; |
| | | // 将找到的最近的点添加到排序列表中,并从原始列表中移除它 |
| | | sortedCoordinates.add(nearest); |
| | | coordinateList.remove(nearest); |
| | | } |
| | | } |
| | | |
| | | return retc; |
| | | |
| | | return sortedCoordinates.toArray(new Coordinate[0]); |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 获取拐点坐标(替换上面获取四个航点坐标方法) |
| | | * |
| | | * @return |
| | | */ |
| | | public static List<Coordinate> getSimplifyPolygons(Geometry originalPolygon) { |
| | | |
| | | List coordinatesList = new ArrayList(); |
| | | |
| | | // 应用抽稀算法,这里使用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); |
| | | } |
| | | |
| | | // 使用Set去除重复项 |
| | | Set<Coordinate> set = new HashSet<>(coordinatesList); |
| | | |
| | | // 将Set转回List |
| | | List<Coordinate> uniqueCoordinates = new ArrayList<>(set); |
| | | |
| | | return uniqueCoordinates; |
| | | } |
| | | |
| | | public static int getSimplifyPolygonsNum(Geometry polygon) { |
| | | // 使用 TopologyPreservingSimplifier 进行抽稀 |
| | | double distanceTolerance = 1.0; // 设置抽稀的容忍度,根据实际需要调整 |
| | | Geometry simplifiedPolygon = TopologyPreservingSimplifier.simplify(polygon, distanceTolerance); |
| | | |
| | | return simplifiedPolygon.getNumPoints(); |
| | | } |
| | | |
| | | public static void main(String[] args) { |
| | | //测试 |
| | |
| | | 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()); |
| | | |
| | | getRoutePointOrder(list); |
| | | |
| | | // 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<PointPO> pointPOS = getRoutePointOrder(list, 28.624514734, 115.856725497); |
| | | |
| | | for (PointPO c : |
| | | pointPOS) { |
| | | System.out.println(c); |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 航线点排序 |
| | | * |
| | | * @return |
| | | */ |
| | | public static List<PointPO> getRoutePointOrder(List<LotInfo> list, double airportLat, double airportLon) { |
| | | List<Coordinate> centros = new ArrayList<>(); |
| | | List<List<Coordinate>> extremePoints = new ArrayList<>(); |
| | | AtomicInteger numSize = new AtomicInteger(); |
| | | |
| | | for (LotInfo patche : list) { |
| | | 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); |
| | | |
| | | double distance = DistanceCalculator.calculateDistance(airportLat, airportLon, coordinateCentro.y,coordinateCentro.x); |
| | | // 机场范围,操作机场范围将不生成 |
| | | if (distance * 1000 > 7000) { |
| | | continue; |
| | | } |
| | | |
| | | centros.add(coordinateCentro); |
| | | |
| | | // 开始封装图斑4个航线 |
| | | // List<Coordinate> coordinatePointList = getExtremePoints(polygon); |
| | | List<Coordinate> coordinatePointList = getSimplifyPolygons(polygon); |
| | | extremePoints.add(coordinatePointList); |
| | | // points.put(coordinateCentro, coordinatePointList); |
| | | |
| | | // 保存稀释拐点之后总数量 |
| | | numSize.set(numSize.get() + coordinatePointList.size()); |
| | | } |
| | | |
| | | |
| | | // 开始排序 |
| | | Coordinate[] coordinates = new Coordinate[centros.size() + 1]; |
| | | List<Coordinate> coordinateList = new ArrayList<>(); |
| | | coordinates[0] = new Coordinate(airportLon, airportLat); //第一个为机场经纬度 |
| | | coordinateList.add(new Coordinate(airportLon, airportLat)); //第一个为机场经纬度) |
| | | for (int i = 1; i < centros.size() + 1; i++) { |
| | | coordinates[i] = centros.get(i - 1); |
| | | coordinateList.add(centros.get(i - 1)); |
| | | } |
| | | |
| | | // 方案一:一个图斑按4个航点规划 |
| | | // // 对中心坐标数组进行排序 |
| | | // Coordinate[] retCoordinate = new Coordinate[coordinateList.size()]; |
| | | // Coordinate[] sortedCoordinates = DistanceCalculator.sortByDistance(coordinateList, airportLat, airportLon, 0, retCoordinate); |
| | | // |
| | | // // 开始拼接图斑点位--按中心坐标数组排序顺序 |
| | | // // 长度-3第一个起点只有一个点位 |
| | | // Coordinate[] retc = new Coordinate[sortedCoordinates.length * 4 - 3]; |
| | | // // 赋值起点 |
| | | // retc[0] = sortedCoordinates[0]; |
| | | // int i = 0; |
| | | // for (Coordinate num : sortedCoordinates) { |
| | | // List<Coordinate> coordinatePoints = points.get(num); |
| | | // if (null != coordinatePoints) { |
| | | // for (int j = 0; j < coordinatePoints.size(); j++) { |
| | | // // 开始拼接 |
| | | // retc[i * coordinatePoints.size() + j - 3] = coordinatePoints.get(j); |
| | | // } |
| | | // } |
| | | // |
| | | // i++; |
| | | // } |
| | | // |
| | | // return retc; |
| | | |
| | | |
| | | // 方案二:抽稀,获取拐点 |
| | | 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++) { |
| | | 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); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | // 根据排序前的索引按顺序赋值 |
| | | int i = 0; |
| | | 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 retcList; |
| | | |
| | | } |
| | | |
| | | } |