package com.ard.work.service.impl; import com.ard.common.constant.UserConstants; import com.ard.common.utils.DateUtils; import com.ard.common.utils.StringUtils; import com.ard.common.utils.uuid.IdUtils; import com.ard.work.domain.dto.wayline.ArdUavPositionDTO; import com.ard.work.domain.dto.wayline.ArdWaylineDTO; import com.ard.work.domain.entity.UavWayline; import com.ard.work.mapper.UavWaylineMapper; import com.ard.work.service.IUavWaylineService; import com.ard.work.service.IKmzFileService; import com.ard.work.util.GeoTools; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.io.IOException; import java.util.List; import java.util.Optional; /** * 航线Service业务层处理 * * @author ard * @date 2025-06-27 */ @Slf4j @Service public class UavWaylineServiceImpl implements IUavWaylineService { ObjectMapper mapper = new ObjectMapper(); @Resource private UavWaylineMapper uavWaylineMapper; @Resource private IKmzFileService waylineFileService; /** * 查询航线 * * @param id 航线主键 * @return 航线 */ @Override public ArdWaylineDTO selectUavWaylineById(String id) { UavWayline uavWayline = uavWaylineMapper.selectUavWaylineById(id); return EntityConverterTowaylineDTO(uavWayline); } /** * 查询航线列表 * * @param uavWayline 航线 * @return 航线 */ @Override public List selectUavWaylineList(UavWayline uavWayline) { return uavWaylineMapper.selectUavWaylineList(uavWayline); } /** * 新增航线 * * @param ardWaylineDTO 航线 * @return 结果 */ @Override public int insertUavWayline(ArdWaylineDTO ardWaylineDTO) { UavWayline uavWayline = waylineDTOConverterToEntity(ardWaylineDTO); uavWayline.setCreateTime(DateUtils.getNowDate()); int row = uavWaylineMapper.insertUavWayline(uavWayline); if (row > 0) { waylineFileService.outputKmz(ardWaylineDTO); } return row; } /** * 修改航线 * * @param ardWaylineDTO 航线 * @return 结果 */ @Override public int updateUavWayline(ArdWaylineDTO ardWaylineDTO) { UavWayline uavWayline = waylineDTOConverterToEntity(ardWaylineDTO); uavWayline.setUpdateTime(DateUtils.getNowDate()); int row = uavWaylineMapper.updateUavWayline(uavWayline); if (row > 0) { waylineFileService.outputKmz(ardWaylineDTO); } return row; } /** * 批量删除航线 * * @param ids 需要删除的航线主键 * @return 结果 */ @Override public int deleteUavWaylineByIds(String[] ids) { return uavWaylineMapper.deleteUavWaylineByIds(ids); } /** * 删除航线信息 * * @param id 航线主键 * @return 结果 */ @Override public int deleteUavWaylineById(String id) { return uavWaylineMapper.deleteUavWaylineById(id); } /** * 校验航线是否唯一 * * @param ardWaylineDTO 航线信息 * @return 结果 */ @Override public boolean checkWaylineNameUnique(ArdWaylineDTO ardWaylineDTO) { String waylineId = ardWaylineDTO.getWaylineId(); UavWayline info = uavWaylineMapper.checkUavWaylineNameUnique(ardWaylineDTO.getWaylineName()); if (StringUtils.isNotNull(info) && !info.getId().equals(waylineId)) { return UserConstants.NOT_UNIQUE; } return UserConstants.UNIQUE; } // DTO转换为实体类 private UavWayline waylineDTOConverterToEntity(ArdWaylineDTO ardWaylineDTO) { UavWayline uavWayline = UavWayline.builder() .id(Optional.ofNullable(ardWaylineDTO.getWaylineId()).orElse(IdUtils.simpleUUID())) .name(ardWaylineDTO.getWaylineName()) .type(ardWaylineDTO.getWaylineType()) .uavModel(ardWaylineDTO.getUavModel()) .payloadModel(ardWaylineDTO.getPayloadModel()) .userWaypointCount(ardWaylineDTO.waylineUserPointCount) .globalSpeed(ardWaylineDTO.getGlobalFlySpeed()) .globalHeight(ardWaylineDTO.getGlobalFlyHeight()) .build(); generateWaylineBytes(ardWaylineDTO, uavWayline); return uavWayline; } // 实体类转换DTO private ArdWaylineDTO EntityConverterTowaylineDTO(UavWayline uavWayline) { try { ArdWaylineDTO ardWaylineDTO = ArdWaylineDTO.builder() .waylineId(uavWayline.getId()) .waylineName(uavWayline.getName()) .waylineType(uavWayline.getType()) .uavModel(uavWayline.getUavModel()) .payloadModel(uavWayline.getPayloadModel()) .waylineUserPointCount(uavWayline.getUserWaypointCount()) .waylineAllPointCount(uavWayline.getPlanWaypointCount()) .globalFlySpeed(uavWayline.getGlobalSpeed()) .globalFlyHeight(uavWayline.getGlobalHeight()) .build(); byte[] planWaylineBytes = uavWayline.getPlanWaylineData(); ardWaylineDTO = mapper.readValue(planWaylineBytes, ArdWaylineDTO.class); //计算长度 double length = calculateWaylineLength(ardWaylineDTO); ardWaylineDTO.setWaylineLength(length); //计算飞行时间 double flyTime = calculateFlyTime(ardWaylineDTO); ardWaylineDTO.setWaylineBaseFlyTime(flyTime); return ardWaylineDTO; } catch (IOException e) { throw new RuntimeException("恢复航线对象错误!" + e.getMessage()); } } // 生成航线字节数组 private void generateWaylineBytes(ArdWaylineDTO ardWaylineDTO, UavWayline uavWayline) { try { ardWaylineDTO.setWaylineId(uavWayline.getId()); //二进制航线编码,保存原始航线数据 byte[] waylineBytes = mapper.writeValueAsBytes(ardWaylineDTO); uavWayline.setSrcWaylineData(waylineBytes); if (ardWaylineDTO.getWaylineType() == 1) { log.info("面向逐点的航线规划!"); byte[] newWaylineBytes = mapper.writeValueAsBytes(ardWaylineDTO); uavWayline.setPlanWaylineData(newWaylineBytes); uavWayline.setPlanWaypointCount(ardWaylineDTO.getWaylineUserPointCount()); } else { log.error("航线设置错误:{}", ardWaylineDTO.getWaylineType()); throw new RuntimeException("航线类型错误" + ardWaylineDTO.getWaylineType()); } } catch (Exception e) { log.error("航线规划失败:{}", e.getMessage()); throw new RuntimeException("航线规划失败!" + e.getMessage()); } } private ArdWaylineDTO deepCopyWayline(ArdWaylineDTO ardWaylineDTO) { ArdWaylineDTO newWaylineDTO = null; try { byte[] waylineBytes = mapper.writeValueAsBytes(ardWaylineDTO); newWaylineDTO = mapper.readValue(waylineBytes, ArdWaylineDTO.class); } catch (JsonProcessingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return newWaylineDTO; } //计算航线长度 public double calculateWaylineLength( ArdWaylineDTO ardWaylineDTO) { List uavPositions = ardWaylineDTO.getUavPositions(); if (uavPositions == null || uavPositions.size() < 2) { return 0.0; } double totalLength = 0.0; for (int i = 1; i < uavPositions.size(); i++) { ArdUavPositionDTO prev = uavPositions.get(i - 1); ArdUavPositionDTO curr = uavPositions.get(i); totalLength += GeoTools.calculateDistance( prev.getUavPosition().getLatitude(), prev.getUavPosition().getLongitude(), curr.getUavPosition().getLatitude(), curr.getUavPosition().getLongitude() ); } return totalLength; } //计算飞行时间 public double calculateFlyTime(ArdWaylineDTO ardWaylineDTO) { double totalLength = calculateWaylineLength(ardWaylineDTO); // 单位:米 Float globalSpeed = ardWaylineDTO.getGlobalFlySpeed(); // 单位:米/秒 if (globalSpeed == null || globalSpeed <= 0) { throw new IllegalArgumentException("全局速度无效,必须大于0"); } return totalLength / globalSpeed; // 返回时间,单位:秒 } }