package com.moral.api.service.impl; import com.alibaba.fastjson.JSONArray; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.moral.api.entity.ManageAccount; import com.moral.api.entity.ManageCoordinate; import com.moral.api.entity.ManageCoordinateDetail; import com.moral.api.entity.SpecialDevice; import com.moral.api.mapper.HistorySecondCruiserMapper; import com.moral.api.mapper.ManageCoordinateDetailMapper; import com.moral.api.mapper.SpecialDeviceMapper; import com.moral.api.pojo.dto.cruiser.CruiserDTO; import com.moral.api.pojo.redisBean.AccountInfoDTO; import com.moral.api.service.ManageCoordinateDetailService; import com.moral.api.util.RoadUtils; import com.moral.constant.RedisConstants; import com.moral.util.DateUtils; import com.moral.util.TokenUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.awt.geom.Point2D; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @Service @Slf4j public class ManageCoordinateDetailServiceImpl extends ServiceImpl implements ManageCoordinateDetailService { @Autowired private ManageCoordinateDetailMapper manageCoordinateDetailMapper; @Autowired private HistorySecondCruiserMapper historySecondCruiserMapper; @Autowired private RedisTemplate redisTemplate; @Autowired private SpecialDeviceMapper specialDeviceMapper; /** * 新增经纬度 * @param params * @return */ @Override @Transactional public Integer insertCoordinate(Map params) { HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); String token = request.getHeader("token"); AccountInfoDTO accountInfoDTO = (AccountInfoDTO) TokenUtils.getUserInfoByToken(token); ManageAccount manageAccount = accountInfoDTO.getAccount(); Integer id = manageAccount.getId(); String userName = manageAccount.getUserName(); int coordinateId = Integer.parseInt(params.get("coordinateId").toString()); List> data = (List>) params.get("data"); for (Map datum : data) { String code = datum.get("code").toString(); String state = datum.get("state").toString(); if (state.equals("2")){ ManageCoordinateDetail manageCoordinateDetail = new ManageCoordinateDetail(); String[] rs = code.split("_"); manageCoordinateDetail.setCoordinateId(coordinateId); manageCoordinateDetail.setLongitude(Double.parseDouble(rs[0])); manageCoordinateDetail.setLatitude(Double.parseDouble(rs[1])); manageCoordinateDetail.setState("2"); manageCoordinateDetail.setUpdateUserId(id); manageCoordinateDetail.setUpdayeUserName(userName); QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("coordinate_id",coordinateId); wrapper.eq("longitude",manageCoordinateDetail.getLongitude()); wrapper.eq("latitude",manageCoordinateDetail.getLatitude()); Integer integer = manageCoordinateDetailMapper.selectCount(wrapper); if (integer>=1){ return 1; } manageCoordinateDetailMapper.insert(manageCoordinateDetail); }else { Object id1 = datum.get("id"); if (ObjectUtils.isEmpty(id1)){ return 2; } manageCoordinateDetailMapper.deleteById(Integer.parseInt(id1.toString())); } } return 200; } /** * 查询坐标点 * @param params * @return */ @Override public Map selectCoordinate(Map params) { HashMap rsMap = new HashMap<>(); String mac = params.get("mac").toString(); String time1 = params.get("time1").toString(); ArrayList rsList1 = new ArrayList<>(); params.put("dateFormat", "%Y-%m-%d %H:%i:%s"); String coordinateId = params.get("coordinateId").toString(); QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("coordinate_id",coordinateId); List manageCoordinateDetails = manageCoordinateDetailMapper.selectList(queryWrapper); List cruiserInfo = (List) redisTemplate.opsForHash().get(RedisConstants.DATE_COORDINATE, mac + time1); if (ObjectUtils.isEmpty(cruiserInfo)){ cruiserInfo = historySecondCruiserMapper.getCruiserInfo(params); cruiserInfo = cruiserInfo.stream().distinct().collect(Collectors.toList()); cruiserInfo.removeIf(o->{ if (ObjectUtils.isEmpty(o.getFlyLon()) || ObjectUtils.isEmpty(o.getFlyLat())) { return true; } double lon = o.getFlyLon(); double lat = o.getFlyLat(); double[] doubles = RoadUtils.transformWGS84ToBD09(lon, lat); Matcher matcher = Pattern.compile("\\d*\\.\\d{8}").matcher(""+doubles[0]); matcher.find(); String s = matcher.group(); Matcher matcher1 = Pattern.compile("\\d*\\.\\d{8}").matcher(""+doubles[1]); matcher1.find(); String s1 = matcher1.group(); o.setFlyLon(Double.parseDouble(s)); o.setFlyLat(Double.parseDouble(s1)); o.setData(lon+"_"+lat); // o.setFlyLon(doubles[0]); // o.setFlyLat(doubles[1]); if (lon < 70 || lon > 150 || lat < 20 || lat > 60) { return true; } return false; }); redisTemplate.opsForHash().put(RedisConstants.DATE_COORDINATE,mac+time1,cruiserInfo); //设置过期时间 redisTemplate.opsForHash().getOperations().expire(RedisConstants.DATE_COORDINATE,6000, TimeUnit.SECONDS); } // List cruiserInfo = historySecondCruiserMapper.getCruiserInfo(params); if (ObjectUtils.isEmpty(manageCoordinateDetails)){ rsMap.put("rsData",cruiserInfo); rsMap.put("data",rsList1); return rsMap; } for (int i=cruiserInfo.size()-1;i>0;i--) { CruiserDTO cruiserDTO = cruiserInfo.get(i); String data = cruiserDTO.getData(); String[] rs = data.split("_"); String flyLon = rs[0]; String flyLat = rs[1]; // double lonDouble = Double.parseDouble(flyLon); // double latDouble = Double.parseDouble(flyLat); for (ManageCoordinateDetail manageCoordinateDetail : manageCoordinateDetails) { String latitude = manageCoordinateDetail.getLatitude().toString(); String longitude = manageCoordinateDetail.getLongitude().toString(); // double lonDouble1 = Double.parseDouble(longitude); // double latDouble1 = Double.parseDouble(latitude); // if (latDouble1==latDouble && lonDouble==lonDouble1){ if (flyLon.equals(longitude) && flyLat.equals(latitude)){ manageCoordinateDetail.setCode(data); manageCoordinateDetail.setLongitude(cruiserDTO.getFlyLon()); manageCoordinateDetail.setLatitude(cruiserDTO.getFlyLat()); rsList1.add(manageCoordinateDetail); cruiserInfo.remove(i); break; } } } rsMap.put("rsData",cruiserInfo); rsMap.put("data",rsList1); return rsMap; } /** * 批量添加 * @param params * @return */ @Override @Transactional public Integer batchAll(Map params) { params.put("dateFormat", "%Y-%m-%d %H:%i:%s"); String type = params.get("type").toString(); int coordinateId = Integer.parseInt(params.get("coordinateId").toString()); QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("coordinate_id",coordinateId); int j =0; List manageCoordinateDetails = manageCoordinateDetailMapper.selectList(queryWrapper); // List cruiserInfo = (List) params.get("list"); List cruiserInfo; //区域选择 if (type.equals("1")){ List> list = (List>) params.get("list"); cruiserInfo = list.stream().distinct() .map(map -> { CruiserDTO p = new CruiserDTO(); Double flylat = (Double) map.get("flylat"); Double flylon = (Double) map.get("flylon"); p.setFlyLat(flylat); p.setFlyLon(flylon); return p; }) .collect(Collectors.toList()); }else { //时间段选择 String time1 = params.remove("time1").toString(); String time2 = params.remove("time2").toString(); long l = DateUtils.compareDateStrDay(time1, time2); if (l>0){ params.put("time1",time1); params.put("time2",time2); }else { params.put("time1",time2); params.put("time2",time1); } cruiserInfo = historySecondCruiserMapper.getCruiserInfo(params); cruiserInfo = cruiserInfo.stream().distinct().collect(Collectors.toList()); } if (ObjectUtils.isEmpty(manageCoordinateDetails)){ for (CruiserDTO cruiserDTO : cruiserInfo) { Double flyLat = cruiserDTO.getFlyLat(); Double flyLon = cruiserDTO.getFlyLon(); if (ObjectUtils.isEmpty(flyLat) || ObjectUtils.isEmpty(flyLon)){ continue; } ManageCoordinateDetail rsDTO = new ManageCoordinateDetail(); rsDTO.setLatitude(flyLat); rsDTO.setLongitude(flyLon); rsDTO.setState("2"); rsDTO.setCreateTime(new Date()); rsDTO.setUpdateTime(new Date()); rsDTO.setCoordinateId(coordinateId); manageCoordinateDetailMapper.insert(rsDTO); j++; log.info(j+""); } }else { Map map = new HashMap<>(manageCoordinateDetails.size()+50); manageCoordinateDetails.forEach(it->map.put(it.getLatitude()+"_"+it.getLongitude(),it.getId())); List result = new ArrayList<>(); for (CruiserDTO cruiserDTO : cruiserInfo) { String fly = cruiserDTO.getFlyLat()+"_"+cruiserDTO.getFlyLon(); if(!map.containsKey(fly)){ ManageCoordinateDetail rsDTO = new ManageCoordinateDetail(); rsDTO.setLatitude(cruiserDTO.getFlyLat()); rsDTO.setLongitude(cruiserDTO.getFlyLon()); rsDTO.setState("2"); rsDTO.setCreateTime(new Date()); rsDTO.setUpdateTime(new Date()); rsDTO.setCoordinateId(coordinateId); result.add(rsDTO); } } if(!CollectionUtils.isEmpty(result)){ this.saveBatch(result); } } return 200; } /** * 所有数据批量添加 * * @param params */ @Override public void queryAll(Map params) { //获取路段信息 List coordinates = specialDeviceMapper.selectCoordinate(params.get("mac").toString()); //获取走航车数据 List cruiserInfo = historySecondCruiserMapper.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); } } /** * 判断当前位置是否在多边形区域内 * @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; } } }