| | |
| | | |
| | | |
| | | 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> |
| | |
| | | @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; |
| | | } |
| | | |
| | | } |