package com.xiaopeng.map.service.serviceimpl;
|
|
|
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>
|
* 电子围栏区域构成 服务实现类
|
* </p>
|
*
|
* @author liu
|
* @since 2026-02-03
|
*/
|
@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;
|
}
|
|
}
|