diff --git a/admin/src/main/java/com/multictrl/common/task/FlightTaskUpdate.java b/admin/src/main/java/com/multictrl/common/task/FlightTaskUpdate.java index 8c0887e..72cc630 100644 --- a/admin/src/main/java/com/multictrl/common/task/FlightTaskUpdate.java +++ b/admin/src/main/java/com/multictrl/common/task/FlightTaskUpdate.java @@ -6,7 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.google.common.collect.Maps; import com.multictrl.common.utils.DateUtils; -import com.multictrl.common.utils.Spatial4jUtils; +import com.multictrl.common.utils.map.Spatial4jUtils; import com.multictrl.modules.business.dao.FlightTaskDao; import com.multictrl.modules.business.entity.FlightTaskEntity; import com.multictrl.modules.business.entity.MediaFileEntity; diff --git a/admin/src/main/java/com/multictrl/common/utils/Utils.java b/admin/src/main/java/com/multictrl/common/utils/Utils.java index cd10fe3..87873c4 100644 --- a/admin/src/main/java/com/multictrl/common/utils/Utils.java +++ b/admin/src/main/java/com/multictrl/common/utils/Utils.java @@ -252,4 +252,31 @@ public class Utils { double result = bytes / Math.pow(1024, exp); return format(result, 2) + " " + pre + "B"; } + + /** + * 将秒转换为分秒 + */ + public static String calculateSeconds(long totalSeconds) { + // 处理负数 + if (totalSeconds < 0) { + return "-" + calculateSeconds(-totalSeconds); + } + + long hours = totalSeconds / 3600; + long minutes = (totalSeconds % 3600) / 60; + long seconds = totalSeconds % 60; + + StringBuilder sb = new StringBuilder(); + if (hours > 0) { + sb.append(hours).append('h'); + } + if (minutes > 0) { + sb.append(minutes).append('m'); + } + // 当所有部分都为0时,至少显示 "0s" + if (seconds > 0 || sb.isEmpty()) { + sb.append(seconds).append('s'); + } + return sb.toString(); + } } diff --git a/admin/src/main/java/com/multictrl/common/utils/kmz/TemplateUtils.java b/admin/src/main/java/com/multictrl/common/utils/kmz/TemplateUtils.java index c4f6c5e..2458b72 100644 --- a/admin/src/main/java/com/multictrl/common/utils/kmz/TemplateUtils.java +++ b/admin/src/main/java/com/multictrl/common/utils/kmz/TemplateUtils.java @@ -68,11 +68,12 @@ public class TemplateUtils { folder.addElement("wpml:globalUseStraightLine").setText("1"); List waypointList = route.getRouteWaypointList(); - for (RouteWaypointDTO waypoint : waypointList) { + for (int i = 0; i < waypointList.size(); i++) { + RouteWaypointDTO waypoint = waypointList.get(i); Element placemark = folder.addElement("Placemark"); Element point = placemark.addElement("Point"); point.addElement("coordinates").setText(waypoint.getLongitude() + "," + waypoint.getLatitude()); - placemark.addElement("wpml:index").setText(waypoint.getWaypointSort() + ""); + placemark.addElement("wpml:index").setText(i + ""); placemark.addElement("wpml:ellipsoidHeight").setText(waypoint.getFlightHeight() + ""); placemark.addElement("wpml:height").setText(waypoint.getFlightHeight() + ""); placemark.addElement("wpml:waypointSpeed").setText(waypoint.getFlightSpeed() + ""); diff --git a/admin/src/main/java/com/multictrl/common/utils/kmz/WaylinesUtils.java b/admin/src/main/java/com/multictrl/common/utils/kmz/WaylinesUtils.java index 3b56c70..1e41432 100644 --- a/admin/src/main/java/com/multictrl/common/utils/kmz/WaylinesUtils.java +++ b/admin/src/main/java/com/multictrl/common/utils/kmz/WaylinesUtils.java @@ -59,11 +59,12 @@ public class WaylinesUtils { //航点信息 List waypointList = route.getRouteWaypointList(); - for (RouteWaypointDTO waypoint : waypointList) { + for (int i = 0; i < waypointList.size(); i++) { + RouteWaypointDTO waypoint = waypointList.get(i); Element placemark = folder.addElement("Placemark"); Element point = placemark.addElement("Point"); point.addElement("coordinates").setText(waypoint.getLongitude() + "," + waypoint.getLatitude()); - placemark.addElement("wpml:index").setText(waypoint.getWaypointSort() + ""); + placemark.addElement("wpml:index").setText(i + ""); placemark.addElement("wpml:executeHeight").setText(waypoint.getFlightHeight() + ""); placemark.addElement("wpml:waypointSpeed").setText(waypoint.getFlightSpeed() + ""); //添加转弯模式/飞机偏航角模式 diff --git a/admin/src/main/java/com/multictrl/common/utils/map/GeoPoint.java b/admin/src/main/java/com/multictrl/common/utils/map/GeoPoint.java new file mode 100644 index 0000000..da08163 --- /dev/null +++ b/admin/src/main/java/com/multictrl/common/utils/map/GeoPoint.java @@ -0,0 +1,36 @@ +package com.multictrl.common.utils.map; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Arrays; +import java.util.List; + +/** + * 经纬度 + * + * @author Sdy + * @since 1.0.0 2026/6/23 + */ + +@NoArgsConstructor +@AllArgsConstructor +@Data +public class GeoPoint { + + private double longitude; + + private double latitude; + + /** + * 构造方法 + * + * @param location 经纬度x,y + */ + public GeoPoint(String location) { + List list = Arrays.asList(location.split(",")); + this.longitude = Double.parseDouble(list.get(0)); + this.latitude = Double.parseDouble(list.get(1)); + } +} diff --git a/admin/src/main/java/com/multictrl/common/utils/map/GeoUtils.java b/admin/src/main/java/com/multictrl/common/utils/map/GeoUtils.java new file mode 100644 index 0000000..5e8a44a --- /dev/null +++ b/admin/src/main/java/com/multictrl/common/utils/map/GeoUtils.java @@ -0,0 +1,245 @@ +package com.multictrl.common.utils.map; + +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.multictrl.common.exception.RenException; + +import java.util.ArrayList; +import java.util.List; + +/** + * 地图数据工具 + * + * @author Sdy + * @since 1.0.0 2026/6/23 + */ +public class GeoUtils { + + private static final int EARTH_RADIUS_IN_METERS = 6371000; // 地球半径,单位:米 + + /** + * 创建wkt点 + * + * @param longitude 精度 + * @param latitude 维度 + * @return 返回WKT格式的点,例如 "POINT(120.123456789 30.987654789)" + */ + public static String createPointWkt(Double longitude, Double latitude) { + if (longitude == null || latitude == null) { + return null; + } + // 判断是否是合法的数字 + if (Double.isNaN(longitude) || Double.isNaN(latitude) || + Double.isInfinite(longitude) || Double.isInfinite(latitude)) { + return null; + } + return String.format("POINT(%.9f %.9f)", longitude, latitude); + } + + /** + * 解析 WKT 格式的 POINT 字符串,并根据指定的精度返回经度和纬度 + * + * @param pointWkt WKT 格式的 POINT 字符串,例如 "POINT(120.123456789 30.987654789)" + * @return 包含经度和纬度的 GeoPoint 对象 + */ + public static GeoPoint parsePointWkt(String pointWkt) { + if (pointWkt == null || !pointWkt.startsWith("POINT(") || !pointWkt.endsWith(")")) { + throw new RenException("经纬度解析错误"); + } + + // 去掉 "POINT(" 和 ")",然后按空格分割 + String content = pointWkt.substring(6, pointWkt.length() - 1); + String[] parts = content.split("\\s+"); + + if (parts.length != 2) { + throw new RenException("经纬度解析错误"); + } + + try { + double longitude = Double.parseDouble(parts[0]); + double latitude = Double.parseDouble(parts[1]); + + // 根据精度进行四舍五入 + longitude = roundToPrecision(longitude, 9); + latitude = roundToPrecision(latitude, 9); + + return new GeoPoint(longitude, latitude); + } catch (Exception e) { + throw new RenException("经纬度解析错误", e); + } + } + + /** + * 四舍五入到指定的小数位数 + * + * @param value 要四舍五入的值 + * @param precision 小数点后保留的位数 + * @return 四舍五入后的结果 + */ + private static double roundToPrecision(double value, int precision) { + double scale = Math.pow(10, precision); + return Math.round(value * scale) / scale; + } + + /** + * 使用 Haversine 公式计算两个经纬度之间的距离(单位:米) + * + * @param lat1 第一个点的纬度 + * @param lon1 第一个点的经度 + * @param lat2 第二个点的纬度 + * @param lon2 第二个点的经度 + * @return 距离(米) + */ + public static double calculateDistance(double lat1, double lon1, double lat2, double lon2) { + double lat1Rad = Math.toRadians(lat1); + double lon1Rad = Math.toRadians(lon1); + double lat2Rad = Math.toRadians(lat2); + double lon2Rad = Math.toRadians(lon2); + + double a = Math.pow(Math.sin((lat2Rad - lat1Rad) / 2), 2) + + Math.cos(lat1Rad) * Math.cos(lat2Rad) * + Math.pow(Math.sin((lon2Rad - lon1Rad) / 2), 2); + + double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + return EARTH_RADIUS_IN_METERS * c; + } + + /** + * 判断两点之间的距离是否在指定范围内(单位:米) + * + * @param lat1 第一个点的纬度 + * @param lon1 第一个点的经度 + * @param lat2 第二个点的纬度 + * @param lon2 第二个点的经度 + * @param minDistance 最小距离(单位:米) + * @param maxDistance 最大距离(单位:米) + * @return 是否在范围内 + */ + public static boolean isDistanceInRange(double lat1, double lon1, double lat2, double lon2, + double minDistance, double maxDistance) { + double distance = calculateDistance(lat1, lon1, lat2, lon2); + return distance >= minDistance && distance <= maxDistance; + } + + /** + * 将 "经度,纬度;经度,纬度" 格式的字符串转换为闭合的坐标数组(用于 GeoJSON Polygon) + * + * @param mapping 输入的坐标字符串 + * @return 格式化后的 List>,每个内层 List 为 [经度, 纬度] + */ + public static List> parseCoordinates(String mapping) { + if (mapping == null || mapping.trim().isEmpty()) { + throw new RenException("面状范围不能为空"); + } + + String[] points = mapping.split(";"); + List> coordinates = new ArrayList<>(); + + List firstPoint = null; + + for (int i = 0; i < points.length; i++) { + String[] latLon = points[i].split(","); + if (latLon.length != 2) { + throw new RenException("无效坐标对: " + points[i]); + } + + double lon = Double.parseDouble(latLon[0].trim()); + double lat = Double.parseDouble(latLon[1].trim()); + + List point = List.of(lon, lat); + coordinates.add(point); + + // 记录第一个点用于闭合 + /*if (i == 0) { + firstPoint = point; + }*/ + } + + // 闭合多边形:最后一个点必须等于第一个点 + /*if (firstPoint != null && !coordinates.get(coordinates.size() - 1).equals(firstPoint)) { + coordinates.add(firstPoint); + }*/ + + return coordinates; + } + + /** + * 根据经纬度获取高程(单位:米) + * + * @param latitude 纬度(如 40.714728) + * @param longitude 经度(如 -73.998672) + * @return 海拔高度(米) + * @throws Exception 如果API请求失败或数据异常 + */ + public static double getElevation(double latitude, double longitude) { + // 构建API请求URL(使用aster30m数据集) + String url = "https://api.opentopodata.org/v1/aster30m?locations=" + latitude + "," + longitude; + + //发送HTTP请求 + String response = HttpUtil.get(url); + + // 解析JSON + JSONObject json = JSONUtil.parseObj(response); + if (!json.containsKey("results") || json.getJSONArray("results").isEmpty()) { + return 0; + } + + // 返回第一个结果的高程值 + return json.getJSONArray("results").getJSONObject(0).getDouble("elevation"); + } + + /** + * 计算点数集合总时长 + * 包含了上升时间 + */ + public static long calculateFlightTime(List waypoints) { + if (waypoints == null || waypoints.size() < 2) { + return 0; + } + + double totalSeconds = 0.0; + final double EARTH_RADIUS = 6371000.0; // 地球半径(米) + final double VERTICAL_SPEED = 2.0; // 垂直调整速度(m/s,大疆典型值) + + for (int i = 1; i < waypoints.size(); i++) { + JSONObject prev = waypoints.get(i - 1); + JSONObject curr = waypoints.get(i); + + // 获取位置和速度 + double lat1 = prev.getDouble("latitude"); + double lon1 = prev.getDouble("longitude"); + double alt1 = prev.getDouble("altitude"); + double lat2 = curr.getDouble("latitude"); + double lon2 = curr.getDouble("longitude"); + double alt2 = curr.getDouble("altitude"); + double horizontalSpeed = prev.getDouble("speed"); // 水平速度(m/s) + + // 1. 计算水平距离(地面投影,单位:米) + double lat1Rad = Math.toRadians(lat1); + double lon1Rad = Math.toRadians(lon1); + double lat2Rad = Math.toRadians(lat2); + double lon2Rad = Math.toRadians(lon2); + + double deltaLat = lat2Rad - lat1Rad; + double deltaLon = lon2Rad - lon1Rad; + + double a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) + + Math.cos(lat1Rad) * Math.cos(lat2Rad) * + Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2); + double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + double groundDistance = EARTH_RADIUS * c; + + // 2. 计算垂直高度差(绝对值) + double heightDiff = Math.abs(alt2 - alt1); + + // 3. 计算两段飞行时间 + double timeVertical = heightDiff / VERTICAL_SPEED; // 垂直调整时间 + double timeHorizontal = groundDistance / horizontalSpeed; // 水平飞行时间 + + totalSeconds += timeVertical + timeHorizontal; + } + + return Math.round(totalSeconds); // 四舍五入为整数秒 + } +} diff --git a/admin/src/main/java/com/multictrl/common/utils/Spatial4jUtils.java b/admin/src/main/java/com/multictrl/common/utils/map/Spatial4jUtils.java similarity index 98% rename from admin/src/main/java/com/multictrl/common/utils/Spatial4jUtils.java rename to admin/src/main/java/com/multictrl/common/utils/map/Spatial4jUtils.java index ea32d32..e80b1c9 100644 --- a/admin/src/main/java/com/multictrl/common/utils/Spatial4jUtils.java +++ b/admin/src/main/java/com/multictrl/common/utils/map/Spatial4jUtils.java @@ -1,4 +1,4 @@ -package com.multictrl.common.utils; +package com.multictrl.common.utils.map; import org.locationtech.spatial4j.context.SpatialContext; import org.locationtech.spatial4j.distance.DistanceUtils; diff --git a/admin/src/main/java/com/multictrl/modules/business/controller/RouteController.java b/admin/src/main/java/com/multictrl/modules/business/controller/RouteController.java index bad2239..0abaa51 100644 --- a/admin/src/main/java/com/multictrl/modules/business/controller/RouteController.java +++ b/admin/src/main/java/com/multictrl/modules/business/controller/RouteController.java @@ -11,9 +11,11 @@ import com.multictrl.common.validator.group.AddGroup; import com.multictrl.common.validator.group.UpdateGroup; import com.multictrl.modules.business.dto.RouteAiDTO; import com.multictrl.modules.business.dto.RouteDTO; +import com.multictrl.modules.business.dto.RouteEstimateTimeDTO; import com.multictrl.modules.business.dto.UploadRouteDTO; import com.multictrl.modules.business.service.RouteService; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.apache.shiro.authz.annotation.RequiresPermissions; @@ -125,13 +127,33 @@ public class RouteController { @Parameter(name = "dockSn", description = "机库SN"), @Parameter(name = "accurateImport", description = "是否精准导入"), @Parameter(name = "globalRthHeight", description = "返航高度"), - @Parameter(name = "file", description = "航线文件") + @Parameter(name = "file", description = "航线文件", + schema = @Schema(type = "string", format = "binary")) }) @RequiresPermissions("bus:route:upload") - public Result upload(UploadRouteDTO dto) { + public Result upload(@Parameter(hidden = true) UploadRouteDTO dto) { ValidatorUtils.validateEntity(dto); routeService.upload(dto); return new Result<>(); } + + @PostMapping("/getWaypointEstimateTime") + @Operation(summary = "航点航线预计飞行时间") + public Result getWaypointEstimateTime(@RequestBody RouteEstimateTimeDTO dto) { + ValidatorUtils.validateEntity(dto); + String estimateTime = routeService.getWaypointEstimateTime(dto); + + return new Result().ok(estimateTime); + } + + @PutMapping("/updateGlobalRthHeight") + @Operation(summary = "修改返航高度") + @LogOperation("修改返航高度") + public Result updateGlobalRthHeight(@RequestParam Long routeId, + @RequestParam Integer globalRthHeight) { + routeService.updateGlobalRthHeight(routeId, globalRthHeight); + + return new Result<>(); + } } diff --git a/admin/src/main/java/com/multictrl/modules/business/dto/RouteEstimateTimeDTO.java b/admin/src/main/java/com/multictrl/modules/business/dto/RouteEstimateTimeDTO.java new file mode 100644 index 0000000..488f022 --- /dev/null +++ b/admin/src/main/java/com/multictrl/modules/business/dto/RouteEstimateTimeDTO.java @@ -0,0 +1,34 @@ +package com.multictrl.modules.business.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.util.List; + +/** + * 航线预计飞行时长参数 + * + * @author Sdy + * @since 1.0.0 2026/6/23 + */ +@Data +@Schema(name = "航线预计飞行时长参数") +public class RouteEstimateTimeDTO { + + @NotBlank(message = "机库SN不能为空") + @Schema(description = "机库SN") + private String dockSn; + + @Schema(description = "全局航线过渡速度") + @NotNull(message = "全局航线过渡速度不能为空") + private Double globalTransitionalSpeed; + + @NotBlank(message = "高度模式不能为空") + @Schema(description = "高度模式") + private String heightModel; + + @Schema(description = "航线航点信息") + private List waypointList; +} diff --git a/admin/src/main/java/com/multictrl/modules/business/service/RouteService.java b/admin/src/main/java/com/multictrl/modules/business/service/RouteService.java index 00518dc..cdfd873 100644 --- a/admin/src/main/java/com/multictrl/modules/business/service/RouteService.java +++ b/admin/src/main/java/com/multictrl/modules/business/service/RouteService.java @@ -4,6 +4,7 @@ import com.multictrl.common.page.PageData; import com.multictrl.common.service.CrudService; import com.multictrl.modules.business.dto.RouteAiDTO; import com.multictrl.modules.business.dto.RouteDTO; +import com.multictrl.modules.business.dto.RouteEstimateTimeDTO; import com.multictrl.modules.business.dto.UploadRouteDTO; import com.multictrl.modules.business.entity.RouteEntity; @@ -40,4 +41,10 @@ public interface RouteService extends CrudService { //上传航线 void upload(UploadRouteDTO dto); + + //获取航点航线预计飞行时间 + String getWaypointEstimateTime(RouteEstimateTimeDTO dto); + + //修改返航高度 + void updateGlobalRthHeight(Long routeId, Integer globalRthHeight); } \ No newline at end of file diff --git a/admin/src/main/java/com/multictrl/modules/business/service/impl/FlightTaskServiceImpl.java b/admin/src/main/java/com/multictrl/modules/business/service/impl/FlightTaskServiceImpl.java index a06ec52..4e5760c 100644 --- a/admin/src/main/java/com/multictrl/modules/business/service/impl/FlightTaskServiceImpl.java +++ b/admin/src/main/java/com/multictrl/modules/business/service/impl/FlightTaskServiceImpl.java @@ -17,6 +17,7 @@ import com.multictrl.common.page.PageData; import com.multictrl.common.service.impl.CrudServiceImpl; import cn.hutool.core.util.StrUtil; import com.multictrl.common.utils.*; +import com.multictrl.common.utils.map.Spatial4jUtils; import com.multictrl.modules.business.dao.DockDeviceDao; import com.multictrl.modules.business.dao.FlightTaskDao; import com.multictrl.modules.business.dao.ZhimouCallbackDao; diff --git a/admin/src/main/java/com/multictrl/modules/business/service/impl/RouteServiceImpl.java b/admin/src/main/java/com/multictrl/modules/business/service/impl/RouteServiceImpl.java index 9d30174..bec6372 100644 --- a/admin/src/main/java/com/multictrl/modules/business/service/impl/RouteServiceImpl.java +++ b/admin/src/main/java/com/multictrl/modules/business/service/impl/RouteServiceImpl.java @@ -2,8 +2,10 @@ package com.multictrl.modules.business.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.FileUtil; +import cn.hutool.json.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.multictrl.common.constant.BusinessConstant; import com.multictrl.common.exception.ErrorCode; import com.multictrl.common.exception.ExceptionUtils; @@ -12,6 +14,9 @@ import com.multictrl.common.page.PageData; import com.multictrl.common.service.impl.CrudServiceImpl; import com.multictrl.common.utils.ConvertUtils; import com.multictrl.common.utils.JsonUtils; +import com.multictrl.common.utils.Utils; +import com.multictrl.common.utils.map.GeoUtils; +import com.multictrl.common.utils.map.Spatial4jUtils; import com.multictrl.common.utils.kmz.KmzUtils; import com.multictrl.common.utils.kmz.WpmlKmlParser; import com.multictrl.common.validator.AssertUtils; @@ -25,6 +30,7 @@ import com.multictrl.modules.business.entity.RouteAiEntity; import com.multictrl.modules.business.entity.RouteEntity; import com.multictrl.modules.business.entity.RouteWaypointEntity; import com.multictrl.modules.business.entity.WaypointActionEntity; +import com.multictrl.modules.business.service.DJIBaseService; import com.multictrl.modules.business.service.MinioService; import com.multictrl.modules.business.service.RouteService; import com.multictrl.modules.security.user.SecurityUser; @@ -53,6 +59,7 @@ public class RouteServiceImpl extends CrudServiceImpl getWrapper(Map params) { @@ -236,7 +243,7 @@ public class RouteServiceImpl extends CrudServiceImpl routeWaypointList = routeDTO.getRouteWaypointList(); handleWaypointAction(routeWaypointList); + //计算总距离 + double total = 0; + for (int i = 0; i < routeWaypointList.size() - 1; i++) { + RouteWaypointDTO p1 = routeWaypointList.get(i); + RouteWaypointDTO p2 = routeWaypointList.get(i + 1); + total += Spatial4jUtils.distance(p1.getLatitude(), p1.getLongitude(), p2.getLatitude(), p2.getLongitude()); + } + //计算预计飞行时长 + RouteEstimateTimeDTO timeDTO = new RouteEstimateTimeDTO(); + timeDTO.setDockSn(dto.getDockSn()); + timeDTO.setGlobalTransitionalSpeed(routeDTO.getGlobalTransitionalSpeed()); + timeDTO.setHeightModel(routeDTO.getHeightModel()); + timeDTO.setWaypointList(routeWaypointList); + String estimateTime = getWaypointEstimateTime(timeDTO); //保存信息 RouteEntity routeEntity = ConvertUtils.sourceToTarget(routeDTO, currentModelClass()); routeEntity.setDeptId(SecurityUser.getDeptId()); routeEntity.setWaypointNum(routeWaypointList.size()); + routeEntity.setTotalDistance(total); + routeEntity.setExpectFlightTime(estimateTime); baseDao.insert(routeEntity); //保存航点信息 saveWaypoint(routeEntity.getId(), routeWaypointList); } + @Override + public String getWaypointEstimateTime(RouteEstimateTimeDTO dto) { + String dockSn = dto.getDockSn(); + LatLonDTO dockLocation = djiBaseService.getDockLocation(dockSn); + List waypointList = dto.getWaypointList(); + List waypoints = new ArrayList<>(); + JSONObject jsonObject = null; + if (dockLocation != null) { + jsonObject = new JSONObject(); + jsonObject.set("longitude", dockLocation.getLongitude()); + jsonObject.set("latitude", dockLocation.getLatitude()); + jsonObject.set("altitude", dockLocation.getHeight()); + jsonObject.set("speed", dto.getGlobalTransitionalSpeed()); + waypoints.add(jsonObject); + } + for (RouteWaypointDTO waypointDTO : waypointList) { + JSONObject object = new JSONObject(); + object.set("longitude", waypointDTO.getLongitude()); + object.set("latitude", waypointDTO.getLatitude()); + object.set("altitude", "relativeToStartPoint".equals(dto.getHeightModel()) ? + waypointDTO.getFlightHeight() + (dockLocation != null ? dockLocation.getHeight() : 0) : waypointDTO.getFlightHeight()); + object.set("speed", waypointDTO.getFlightSpeed()); + waypoints.add(object); + } + + long totalTravelTime = GeoUtils.calculateFlightTime(waypoints); + return Utils.calculateSeconds(totalTravelTime); + } + + @Override + public void updateGlobalRthHeight(Long routeId, Integer globalRthHeight) { + baseDao.update(new UpdateWrapper() + .set("global_rth_height", globalRthHeight) + .eq("id", routeId)); + } + //判断航线是否存在 private void checkRouteExist(Long id, String routeName) { RouteEntity uavRouteEntity = baseDao.selectOne(new QueryWrapper()