parent
559fdb5d96
commit
64335ed9d6
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,11 +68,12 @@ public class TemplateUtils {
|
|||
folder.addElement("wpml:globalUseStraightLine").setText("1");
|
||||
|
||||
List<RouteWaypointDTO> 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() + "");
|
||||
|
|
|
|||
|
|
@ -59,11 +59,12 @@ public class WaylinesUtils {
|
|||
|
||||
//航点信息
|
||||
List<RouteWaypointDTO> 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() + "");
|
||||
//添加转弯模式/飞机偏航角模式
|
||||
|
|
|
|||
|
|
@ -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<String> list = Arrays.asList(location.split(","));
|
||||
this.longitude = Double.parseDouble(list.get(0));
|
||||
this.latitude = Double.parseDouble(list.get(1));
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Double>>,每个内层 List 为 [经度, 纬度]
|
||||
*/
|
||||
public static List<List<Double>> parseCoordinates(String mapping) {
|
||||
if (mapping == null || mapping.trim().isEmpty()) {
|
||||
throw new RenException("面状范围不能为空");
|
||||
}
|
||||
|
||||
String[] points = mapping.split(";");
|
||||
List<List<Double>> coordinates = new ArrayList<>();
|
||||
|
||||
List<Double> 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<Double> 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<JSONObject> 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); // 四舍五入为整数秒
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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<Object> upload(UploadRouteDTO dto) {
|
||||
public Result<Object> upload(@Parameter(hidden = true) UploadRouteDTO dto) {
|
||||
ValidatorUtils.validateEntity(dto);
|
||||
routeService.upload(dto);
|
||||
|
||||
return new Result<>();
|
||||
}
|
||||
|
||||
@PostMapping("/getWaypointEstimateTime")
|
||||
@Operation(summary = "航点航线预计飞行时间")
|
||||
public Result<String> getWaypointEstimateTime(@RequestBody RouteEstimateTimeDTO dto) {
|
||||
ValidatorUtils.validateEntity(dto);
|
||||
String estimateTime = routeService.getWaypointEstimateTime(dto);
|
||||
|
||||
return new Result<String>().ok(estimateTime);
|
||||
}
|
||||
|
||||
@PutMapping("/updateGlobalRthHeight")
|
||||
@Operation(summary = "修改返航高度")
|
||||
@LogOperation("修改返航高度")
|
||||
public Result<Object> updateGlobalRthHeight(@RequestParam Long routeId,
|
||||
@RequestParam Integer globalRthHeight) {
|
||||
routeService.updateGlobalRthHeight(routeId, globalRthHeight);
|
||||
|
||||
return new Result<>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<RouteWaypointDTO> waypointList;
|
||||
}
|
||||
|
|
@ -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<RouteEntity, RouteDTO> {
|
|||
|
||||
//上传航线
|
||||
void upload(UploadRouteDTO dto);
|
||||
|
||||
//获取航点航线预计飞行时间
|
||||
String getWaypointEstimateTime(RouteEstimateTimeDTO dto);
|
||||
|
||||
//修改返航高度
|
||||
void updateGlobalRthHeight(Long routeId, Integer globalRthHeight);
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<RouteDao, RouteEntity, Rou
|
|||
private final WaypointActionDao waypointActionDao;
|
||||
private final MinioService minioService;
|
||||
private final RouteAiDao routeAiDao;
|
||||
private final DJIBaseService djiBaseService;
|
||||
|
||||
@Override
|
||||
public QueryWrapper<RouteEntity> getWrapper(Map<String, Object> params) {
|
||||
|
|
@ -236,7 +243,7 @@ public class RouteServiceImpl extends CrudServiceImpl<RouteDao, RouteEntity, Rou
|
|||
byte[] waylines = kmzInfo.get("waylines.wpml");
|
||||
WpmlKmlParser.parseWpmlFile(waylines, routeDTO, dto.getAccurateImport());
|
||||
|
||||
log.debug("解析结果:{}", JsonUtils.toJsonString(dto));
|
||||
log.debug("解析结果:{}", JsonUtils.toJsonString(routeDTO));
|
||||
} catch (Exception e) {
|
||||
log.error("解析结果失败:{}", ExceptionUtils.getErrorStackTrace(e));
|
||||
// throw new RenException(ErrorCode.FILE_PARSER_ERROR);
|
||||
|
|
@ -244,7 +251,9 @@ public class RouteServiceImpl extends CrudServiceImpl<RouteDao, RouteEntity, Rou
|
|||
}
|
||||
|
||||
routeDTO.setRouteName(name);
|
||||
routeDTO.setGlobalRthHeight(dto.getGlobalRthHeight());
|
||||
if (dto.getAccurateImport()) {
|
||||
routeDTO.setGlobalRthHeight(dto.getGlobalRthHeight());
|
||||
}
|
||||
String path = dto.getDockSn() + "/" + originalFilename;
|
||||
try {
|
||||
minioService.uploadFile(file.getInputStream(), BusinessConstant.ROUTE_KMZ_BUCKET, path);
|
||||
|
|
@ -259,17 +268,69 @@ public class RouteServiceImpl extends CrudServiceImpl<RouteDao, RouteEntity, Rou
|
|||
//航点动作处理
|
||||
List<RouteWaypointDTO> 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<RouteWaypointDTO> waypointList = dto.getWaypointList();
|
||||
List<JSONObject> 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<RouteEntity>()
|
||||
.set("global_rth_height", globalRthHeight)
|
||||
.eq("id", routeId));
|
||||
}
|
||||
|
||||
//判断航线是否存在
|
||||
private void checkRouteExist(Long id, String routeName) {
|
||||
RouteEntity uavRouteEntity = baseDao.selectOne(new QueryWrapper<RouteEntity>()
|
||||
|
|
|
|||
Loading…
Reference in New Issue