package com.moral.api.service.impl; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import com.alibaba.fastjson.JSONArray; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.moral.api.entity.CruiserDTO; import com.moral.api.entity.ManageCoordinate; import com.moral.api.entity.ManageCoordinateDetail; import com.moral.api.mapper.ManageCoordinateDetailMapper; import com.moral.api.service.ManageCoordinateDetailService; import com.moral.util.DateUtils; /** * Description //todo * * @author swb * @ClassName ManageCoordinateDetailServiceImpl * @date 2024.06.19 09:23 */ @Service @Slf4j public class ManageCoordinateDetailServiceImpl extends ServiceImpl implements ManageCoordinateDetailService { @Autowired private ManageCoordinateDetailMapper manageCoordinateDetailMapper; @Override @Transactional public void insertCoordinateDetail(String startTime,String endTime) { HashMap params = new HashMap<>(); if (ObjectUtils.isEmpty(startTime)&&ObjectUtils.isEmpty(endTime)){ //当前时间的前一天 startTime = DateUtils.getDateStringOfDay(-1, DateUtils.yyyy_MM_dd_HH_mm_ss_EN); //获取当前时间 endTime = DateUtils.getCurDate(DateUtils.yyyy_MM_dd_HH_mm_ss_EN); } params.put("startTime",startTime); params.put("endTime",endTime); //获取路段信息 List coordinates = manageCoordinateDetailMapper.selectCoordinate(); //获取走航车数据 List cruiserInfo = manageCoordinateDetailMapper.getCruiserInfo(params); cruiserInfo = cruiserInfo.stream().distinct().collect(Collectors.toList()); List result = new ArrayList<>(); for (ManageCoordinate coordinate : coordinates) { String value = coordinate.getValue(); if (!ObjectUtils.isEmpty(value)){ List> parse = (List>) JSONArray.parse(value); for (int i = 0; i < cruiserInfo.size(); i++) { CruiserDTO cruiserDTO = cruiserInfo.get(i); if (ObjectUtils.isEmpty(cruiserDTO)){ continue; } Double flyLat = cruiserDTO.getFlyLat(); Double flyLon = cruiserDTO.getFlyLon(); if (ObjectUtils.isEmpty(flyLat)||ObjectUtils.isEmpty(flyLon)){ continue; } boolean inPolygon = isInPolygon(flyLon, flyLat, parse); if (inPolygon){ LambdaQueryWrapper wr = new LambdaQueryWrapper<>(); wr.eq(ManageCoordinateDetail::getLongitude,flyLon); wr.eq(ManageCoordinateDetail::getLatitude,flyLat); List manageCoordinateDetails = manageCoordinateDetailMapper.selectList(wr); if (ObjectUtils.isEmpty(manageCoordinateDetails)){ ManageCoordinateDetail rsDTO = new ManageCoordinateDetail(); rsDTO.setLatitude(flyLat); rsDTO.setLongitude(flyLon); rsDTO.setState("2"); rsDTO.setCreateTime(new Date()); rsDTO.setUpdateTime(new Date()); rsDTO.setCoordinateId(coordinate.getCoordinateId()); result.add(rsDTO); cruiserInfo.remove(i); i--; } } } } } if(!CollectionUtils.isEmpty(result)){ this.saveBatch(result); // log.info(result.size()+""); } } /** * 判断当前位置是否在多边形区域内 * @param * @param mapList 区域顶点 * @return */ public static boolean isInPolygon(Double X,Double Y,List> mapList){ Point2D.Double point = new Point2D.Double(X, Y); List pointList= new ArrayList(); for (Map param : mapList) { //纬度 String lat = param.get("lat").toString(); //经度 String lng = param.get("lng").toString(); Point2D.Double polygonPoint = new Point2D.Double(Double.parseDouble(lng),Double.parseDouble(lat)); pointList.add(polygonPoint); } return IsPtInPoly(point,pointList); } /** * 判断点是否在多边形内,如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true * @param point 检测点 * @param pts 多边形的顶点 * @return 点在多边形内返回true,否则返回false */ public static boolean IsPtInPoly(Point2D.Double point, List pts){ int N = pts.size(); boolean boundOrVertex = true; //如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true int intersectCount = 0;//cross points count of x double precision = 2e-10; //浮点类型计算时候与0比较时候的容差 Point2D.Double p1, p2;//neighbour bound vertices Point2D.Double p = point; //当前点 p1 = pts.get(0);//left vertex for(int i = 1; i <= N; ++i){//check all rays if(p.equals(p1)){ return boundOrVertex;//p is an vertex } p2 = pts.get(i % N); if(p.x < Math.min(p1.x, p2.x) || p.x > Math.max(p1.x, p2.x)){ p1 = p2; continue; } if(p.x > Math.min(p1.x, p2.x) && p.x < Math.max(p1.x, p2.x)){ if(p.y <= Math.max(p1.y, p2.y)){ if(p1.x == p2.x && p.y >= Math.min(p1.y, p2.y)){ return boundOrVertex; } if(p1.y == p2.y){ if(p1.y == p.y){ return boundOrVertex; }else{//before ray ++intersectCount; } }else{ double xinters = (p.x - p1.x) * (p2.y - p1.y) / (p2.x - p1.x) + p1.y; if(Math.abs(p.y - xinters) < precision){ return boundOrVertex; } if(p.y < xinters){ ++intersectCount; } } } }else{ if(p.x == p2.x && p.y <= p2.y){ Point2D.Double p3 = pts.get((i+1) % N); if(p.x >= Math.min(p1.x, p3.x) && p.x <= Math.max(p1.x, p3.x)){ ++intersectCount; }else{ intersectCount += 2; } } } p1 = p2; } if(intersectCount % 2 == 0){//偶数在多边形外 return false; } else { //奇数在多边形内 return true; } } }