GarOrderAssociationServiceAsync.java 8.02 KB
package com.trash.garbage.service.impl;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.trash.common.utils.RemoteServerUtils;
import com.trash.dropPointInfo.service.IDropPointInfoService;
import com.trash.garbage.pojo.domain.GarOrder;
import com.trash.garbage.pojo.domain.GarOrderMatchAsk;
import com.trash.garbage.pojo.dto.AskTransportDto;
import com.trash.garbage.pojo.dto.UploadDto;
import com.trash.garbage.service.GarOrderMatchAskService;

/**
 * 电子联单服务
 */
@EnableAsync
@Component
public class GarOrderAssociationServiceAsync {
    private static final Logger log = LoggerFactory.getLogger(GarOrderAssociationServiceAsync.class);

    @Autowired
    private GarOrderMatchAskService askService;

    @Autowired
    private IDropPointInfoService dropPointInfoService;

    @Autowired
    private com.trash.common.config.trashConfig trashConfig;
    /**
     * 判断车辆是否在投放点区域内
     * @param carPlate 车牌号
     * @param garOrderMatchAsk 订单关联台账
     * @param dto 上传对象
     */
    @Async
    public void isWithinDropPointCoordinates(String carPlate, GarOrderMatchAsk garOrderMatchAsk, UploadDto dto, GarOrder garOrder) {
        try {
            log.info("开始判断车辆是否在投放点区域内");

            // 上传装车照片的经纬度
            double vehicleLat = dto.getLatitude();
            double vehicleLon = dto.getLongitude();
            // 获取投放点的经纬度
            double dropPointLat = garOrder.getGarLatitude();
            double dropPointLon = garOrder.getGarLongitude();
            garOrderMatchAsk.setLoadingLonLat(dto.getLongitude()+","+dto.getLatitude());
            // 计算距离
            double distance = calculateDistance(vehicleLat, vehicleLon, dropPointLat, dropPointLon);
            log.info("车辆与投放点的距离为: {} 公里", distance);
            // 判断是否在1公里内
            if(distance <= 2.0){
                garOrderMatchAsk.setGarOrderType("0");
            }else{
                garOrderMatchAsk.setGarOrderType("1");
                log.info("{}车辆装车地点与投放点{}距离大于2公里,距离:{}", carPlate, garOrder.getGarOrderAddress()+garOrder.getGarOrderAddressDetails(),distance);
                garOrderMatchAsk.setGarRemark(carPlate+"车辆装车地点与投放点<"+garOrder.getGarOrderAddress()+garOrder.getGarOrderAddressDetails()+">距离大于2公里,距离:"+distance+"公里");
            }
        }catch (Exception e){
            log.error("判断车辆是否在投放点区域内发生异常: ", e);
        }finally {
            askService.updateById(garOrderMatchAsk);
            log.info("判断车辆是否在投放点区域内结束");
        }

    }

    /**
     * 判断车辆是否在处置场所内
     * @param carPlate 车牌号
     * @param garOrderMatchAsk 订单关联台账
     * @param dto 上传对象
     */
    @Async
    public void isWithinDisposal(String carPlate, GarOrderMatchAsk garOrderMatchAsk, AskTransportDto dto) {
        try {
            log.info("开始判断车辆是否在处置场所内");
            // 假设 garOrderMatchAsk.getDisposalId() 返回处置场所的 ID
            String token = trashConfig.getToken();
            if (!token.contains("Bearer")){
                token = "Bearer " + token;
            }
            String data = RemoteServerUtils.getEarthSitesDetails(token,garOrderMatchAsk.getDisposalId());
            JSONObject disposalJson = JSON.parseObject(data);
            JSONObject result = disposalJson.getJSONObject("result");
            JSONObject site = result.getJSONObject("site");
            String coord = site.getString("coord");
            // 上传卸车照片的经纬度
            double vehicleLat = dto.getLatitude();
            double vehicleLon = dto.getLongitude();
            garOrderMatchAsk.setUnloadingLonLat(dto.getLongitude()+","+dto.getLatitude());
            // 获取处置场所的经纬度列表
            List<double[]> coordinates = parseCoordinates(coord);
            
            
            coordinates = com.trash.garbage.utils.DistanceUtil.expansion(coordinates, 200);
            // 判断是否在多边形内
            boolean isInside = isPointInPolygon(vehicleLat, vehicleLon, coordinates);
            if (isInside) {
                if(!garOrderMatchAsk.getGarOrderType().equals("1")){
                    garOrderMatchAsk.setGarOrderType("0");
                }
            } else {
                garOrderMatchAsk.setGarOrderType("1");
                log.info("{} 车辆卸车地点不在处置场所 {} 区域内", carPlate, garOrderMatchAsk.getDisposalSiteName());
                if(garOrderMatchAsk.getGarRemark()==null){
                    garOrderMatchAsk.setGarRemark(carPlate + "车辆卸车地点未在处置场所<" + garOrderMatchAsk.getDisposalSiteName() + ">区域内");
                }else{
                    garOrderMatchAsk.setGarRemark(garOrderMatchAsk.getGarRemark()+";"+carPlate + "车辆卸车地点未在处置场所<" + garOrderMatchAsk.getDisposalSiteName() + ">区域内");
                }

            }
        } catch (Exception e) {
            log.error("判断车辆是否在处置场所内发生异常: ", e);
        } finally {
            askService.updateById(garOrderMatchAsk);
            log.info("判断车辆是否在处置场所内结束");
        }

    }

    /**
     * 解析坐标字符串为经纬度列表
     * @param coordinatePoint 坐标字符串,格式为 "lat1,lon1;lat2,lon2;..."
     * @return 经纬度列表
     */
    private List<double[]> parseCoordinates(String coordinatePoint) {
        List<double[]> coordinates = new ArrayList<>();
        String[] points = coordinatePoint.split(";");
        for (String point : points) {
            String[] latLon = point.split(",");
            double lat = Double.parseDouble(latLon[1]);
            double lon = Double.parseDouble(latLon[0]);
            coordinates.add(new double[]{lat, lon});
        }
        return coordinates;
    }

    /**
     * 判断点是否在多边形内(射线法)
     * @param lat 点的纬度
     * @param lon 点的经度
     * @param polygon 多边形的顶点列表
     * @return 点是否在多边形内
     */
    private boolean isPointInPolygon(double lat, double lon, List<double[]> polygon) {
        int n = polygon.size();
        boolean inside = false;
        for (int i = 0, j = n - 1; i < n; j = i++) {
            double[] p1 = polygon.get(i);
            double[] p2 = polygon.get(j);
            if (((p1[1] > lon) != (p2[1] > lon)) &&
                    (lat < (p2[0] - p1[0]) * (lon - p1[1]) / (p2[1] - p1[1]) + p1[0])) {
                inside = !inside;
            }
        }
        return inside;
    }

    /**
     * 计算两个经纬度点之间的距离(单位:公里)
     * @param lat1 第一个点的纬度
     * @param lon1 第一个点的经度
     * @param lat2 第二个点的纬度
     * @param lon2 第二个点的经度
     * @return 两个点之间的距离(公里)
     */
    public static double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
        final int R = 6371; // 地球半径,单位:公里
        double latDistance = Math.toRadians(lat2 - lat1);
        double lonDistance = Math.toRadians(lon2 - lon1);
        double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
                + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
                * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        double distance = R * c;
        // 保留4位小数
        return Math.round(distance * 10000.0) / 10000.0;
    }

}