puzhibing
2026-02-04 85bafa86f44fbe6646019fd8ecbab79f552ccd0a
xp-service/xp-map/src/main/java/com/xiaopeng/map/service/serviceimpl/XpElectronicFenceAreaServiceImpl.java
@@ -2,13 +2,39 @@
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.dto.map.RouteAndFareDto;
import com.xiaopeng.api.dto.operation.LonLatDto;
import com.xiaopeng.api.feignClient.operation.XpSystemSettingClient;
import com.xiaopeng.api.model.operation.XpElectronicFenceArea;
import com.xiaopeng.api.model.operation.XpSystemSetting;
import com.xiaopeng.api.vo.operation.XpElectronicFenceVo;
import com.xiaopeng.api.vo.operation.XpPointsVo;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.map.dto.WalkTimeDto;
import com.xiaopeng.map.mapper.XpElectronicFenceAreaMapper;
import com.xiaopeng.map.repository.XpGeoFencingPolygonRepository;
import com.xiaopeng.map.service.XpElectronicFenceAreaService;
import com.xiaopeng.map.utils.AmapGeoFenceUtil;
import com.xiaopeng.map.utils.AmapWalkingRouteUtil;
import com.xiaopeng.map.utils.ElectricFenceUtil;
import com.xiaopeng.map.utils.mangoUtils.MongoGeoFenceUtil;
import com.xiaopeng.map.vo.IsInOperationAreaVo;
import com.xiaopeng.map.vo.WalkTimeVo;
import com.xiaopeng.map.vo.XpGeoFencingPolygon;
import io.netty.util.concurrent.DefaultThreadFactory;
import org.springframework.data.geo.Point;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
 * <p>
@@ -21,8 +47,215 @@
@Service
public class XpElectronicFenceAreaServiceImpl extends ServiceImpl<XpElectronicFenceAreaMapper, XpElectronicFenceArea> implements XpElectronicFenceAreaService {
    @Resource
    private XpSystemSettingClient xpSystemSettingClient;
    @Resource
    private XpGeoFencingPolygonRepository xpGeoFencingPolygonRepository;
    @Resource
    private AmapGeoFenceUtil amapGeoFenceUtil;
    @Override
    public List<XpElectronicFenceVo> citiesList() {
        List<XpGeoFencingPolygon> xpGeoFencingPolygons = xpGeoFencingPolygonRepository.findAll();
        List<XpElectronicFenceVo> result = new ArrayList<>();
        for (XpGeoFencingPolygon polygon : xpGeoFencingPolygons) {
            XpElectronicFenceVo vo = new XpElectronicFenceVo();
            // 设置id(使用siteId作为id)
            vo.setFenceId(polygon.getFenceId());
            // 设置围栏名称
            vo.setName(polygon.getName());
            // 转换GeoJsonPolygon为List<XpPointsVo>
            List<XpPointsVo> pointsVoList = new ArrayList<>();
            if (polygon.getPoints() != null && polygon.getPoints().getCoordinates() != null) {
                // GeoJsonPolygon的coordinates是一个二维数组,第一个元素是外部环
                List<Point> points = polygon.getPoints().getPoints();
                for (Point coord : points) {
                    XpPointsVo pointsVo = new XpPointsVo();
                    // GeoJson的坐标顺序是[经度, 纬度]
                    pointsVo.setLng(coord.getY());
                    pointsVo.setLat(coord.getX());
                    pointsVoList.add(pointsVo);
                }
            }
            vo.setPoints(pointsVoList);
            result.add(vo);
        }
        return result;
    }
    /**
     * 从MongoDB获取所有地理围栏多边形数据
     * @return 地理围栏多边形列表
     */
    public List<XpGeoFencingPolygon> getAllGeoFencingPolygons() {
        return xpGeoFencingPolygonRepository.findAll();
    }
    /**
     * 根据围栏id从MongoDB获取地理围栏多边形数据
     * @param siteId 围栏id
     * @return 地理围栏多边形
     */
    public XpGeoFencingPolygon getGeoFencingPolygonBySiteId(Integer siteId) {
        return xpGeoFencingPolygonRepository.findBySiteId(siteId);
    }
    /**
     * 根据围栏名称从MongoDB获取地理围栏多边形数据
     * @param name 围栏名称
     * @return 地理围栏多边形列表
     */
    public List<XpGeoFencingPolygon> getGeoFencingPolygonsByName(String name) {
        if (name == null) {
            return xpGeoFencingPolygonRepository.findAll();
        }
        return xpGeoFencingPolygonRepository.findByName(name);
    }
    @Resource
    private MongoGeoFenceUtil mongoGeoFenceUtil;
    /**
     * 判断经纬度是否在开放区域中
     * @param dto
     * @return
     */
    @Override
    public IsInOperationAreaVo isInOperationArea(LonLatDto dto) {
        IsInOperationAreaVo vo = new IsInOperationAreaVo();
        // 组装数据
        MongoGeoFenceUtil.GeoPoint geoPoint = new MongoGeoFenceUtil.GeoPoint(dto.getLongitude(),dto.getLatitude());
        List<String> operatingArea = mongoGeoFenceUtil.findFencesContainingPoint(geoPoint, "operating_area", "points");
        if (!operatingArea.isEmpty()) {
            vo.setStatus("inside");
        }
        return vo;
//        try {
//            executor.execute(() -> {
//                for (XpElectronicFenceVo xpElectronicFenceVo : xpElectronicFenceVos) {
//                    ArrayList<AmapGeoFenceUtil.GeoPoint> geoPoints = new ArrayList<>();
//                    // 获取多边形顶点坐标
//                    List<XpPointsVo> points = xpElectronicFenceVo.getPoints();
//                    for (XpPointsVo point : points) {
//                        geoPoints.add(new AmapGeoFenceUtil.GeoPoint(point.getLng(), point.getLat()));
//                    }
//                    AmapGeoFenceUtil.GeoFence geoFence = new AmapGeoFenceUtil.GeoFence();
//                    geoFence.setPoints(geoPoints);
//
//                    AmapGeoFenceUtil.GeoFenceResult geoFenceResult = null;
//                    try {
//
//
//                        ElectricFenceUtil.areaMonitoring()
//                        geoFenceResult = amapGeoFenceUtil.checkInPolygonFence(geoPoint, geoFence);
//                        if (geoFenceResult.isInFence()) {
//                            vo.setStatus("inside");
//                        }
//                    } catch (IOException e) {
//                        throw new RuntimeException(e);
//                    }
//                }
//            });
//            return vo;
//        }catch (Exception e){
//            e.printStackTrace();
//            vo.setStatus("outside");
//        }finally {
//            gracefulShutdown(executor);
//        }
//
//        return vo;
    }
    /**
     * 优雅关闭线程池通用方法
     *
     * @param pool 需要关闭的线程池
     */
    private static void gracefulShutdown(ExecutorService pool) {
        pool.shutdown(); // 拒绝新任务提交
        try {
            // 等待现有任务完成
            if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
                pool.shutdownNow(); // 取消等待中的任务 只等待运行中的任务
                // 再次等待任务响应中断
                if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
                }
            }
        } catch (InterruptedException e) {
            // 重新尝试关闭
            pool.shutdownNow();
            Thread.currentThread().interrupt();
        } finally {
        }
    }
    @Override
    public WalkTimeVo getWalkTime(WalkTimeDto dto) {
        WalkTimeVo walkTimeVo = new WalkTimeVo();
        // TODO 高德key
        AmapWalkingRouteUtil util = new AmapWalkingRouteUtil("");
        // 示例1:使用经纬度直接查询
        System.out.println("=== 示例1:直接使用经纬度查询 ===");
        AmapWalkingRouteUtil.Location origin = new AmapWalkingRouteUtil.Location(dto.getStartLongitude(), dto.getStartLatitude());  // 天安门
        AmapWalkingRouteUtil.Location destination = new AmapWalkingRouteUtil.Location(dto.getEndLongitude(), dto.getEndLatitude());  // 王府井
        AmapWalkingRouteUtil.WalkingRouteResult result = util.getWalkingRoute(origin, destination);
        if (result.isSuccess()) {
            System.out.println("预计时间: " + result.getFormattedDuration());
            System.out.println("步行距离: " + result.getFormattedDistance());
            walkTimeVo.setWalkTime(result.getFormattedDuration());
            walkTimeVo.setWalkDistance(result.getDistance());
            walkTimeVo.setWalkDistance(result.getDistance());
            R r = xpSystemSettingClient.getOrderDistance();
            if (r.getCode()==200) {
                Object orderDistance = r.getData();
                if (orderDistance != null) {
                    Double orderDistanceDouble = Double.parseDouble(orderDistance.toString());
                    if(orderDistanceDouble>result.getDistance()){
                        walkTimeVo.setStatus(1);
                    }
                }
            }
            return walkTimeVo;
        }else {
            System.out.println("错误信息: " + result.getMessage());
            // 抛出异常
            throw new RuntimeException(result.getMessage());
        }
    }
    @Override
    public Boolean diagnosisArea(RouteAndFareDto dto) {
        // 起点数据
        MongoGeoFenceUtil.GeoPoint startPoint = new MongoGeoFenceUtil.GeoPoint(dto.getOrigin().getLongitude(),dto.getOrigin().getLatitude());
        // 终点数据
        MongoGeoFenceUtil.GeoPoint endPoint = new MongoGeoFenceUtil.GeoPoint(dto.getDestination().getLongitude(),dto.getDestination().getLatitude());
        List<String> operatingArea = mongoGeoFenceUtil.findFencesContainingPoint(startPoint, "operating_area", "points");
        if (!operatingArea.isEmpty()) {
            List<String> operatingArea2 = mongoGeoFenceUtil.findFencesContainingPoint(endPoint, "operating_area", "points");
            if (!operatingArea2.isEmpty()) {
                // "开始判断是否在相同区域";
                if(operatingArea.get(0).equals(operatingArea2.get(0))){
                    return true;
                }
            }
        }
        return null;
    }
}