| | |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.core.common.SpringUtils; |
| | | import com.core.exception.CoolException; |
| | | import com.zy.asrs.entity.BasMap; |
| | |
| | | |
| | | public List<List<NavigateNode>> getStationMap(int lev) { |
| | | BasMapService basMapService = SpringUtils.getBean(BasMapService.class); |
| | | BasMap basMap = basMapService.selectOne(new EntityWrapper<BasMap>().eq("lev", lev)); |
| | | BasMap basMap = basMapService.getOne(new QueryWrapper<BasMap>().eq("lev", lev)); |
| | | if (basMap == null) { |
| | | throw new CoolException("地图不存在"); |
| | | } |
| | |
| | | |
| | | public List<List<NavigateNode>> getRgvTrackMap(int lev) { |
| | | BasMapService basMapService = SpringUtils.getBean(BasMapService.class); |
| | | BasMap basMap = basMapService.selectOne(new EntityWrapper<BasMap>().eq("lev", lev)); |
| | | BasMap basMap = basMapService.getOne(new QueryWrapper<BasMap>().eq("lev", lev)); |
| | | if (basMap == null) { |
| | | throw new CoolException("地图不存在"); |
| | | } |
| | |
| | | int maxPaths, // 最大返回条数. 建议:100/500/2000;<=0 表示不限制(不建议) |
| | | int maxCost // 最大总代价(含拐点惩罚). <=0 表示不限制 |
| | | ) { |
| | | return allSimplePaths(map, start, end, maxDepth, maxPaths, maxCost, Collections.emptyList()); |
| | | } |
| | | |
| | | public List<List<NavigateNode>> allSimplePaths( |
| | | List<List<NavigateNode>> map, |
| | | NavigateNode start, |
| | | NavigateNode end, |
| | | int maxDepth, |
| | | int maxPaths, |
| | | int maxCost, |
| | | List<Integer> guideStationIds |
| | | ) { |
| | | List<List<NavigateNode>> results = new ArrayList<>(); |
| | | if (map == null || map.isEmpty() || map.get(0).isEmpty()) return results; |
| | | if (start == null || end == null) return results; |
| | |
| | | path.add(start); |
| | | |
| | | AtomicInteger pathCount = new AtomicInteger(0); |
| | | Map<Integer, NavigateNode> guideNodeMap = buildGuideNodeMap(map, guideStationIds); |
| | | |
| | | dfsAllSimplePaths(map, start, end, |
| | | visited, path, results, |
| | | 0, // depth |
| | | 0, // cost |
| | | maxDepth, maxPaths, maxCost, |
| | | pathCount |
| | | pathCount, |
| | | guideStationIds, |
| | | guideNodeMap |
| | | ); |
| | | |
| | | return results; |
| | |
| | | int maxDepth, |
| | | int maxPaths, |
| | | int maxCost, |
| | | AtomicInteger pathCount |
| | | AtomicInteger pathCount, |
| | | List<Integer> guideStationIds, |
| | | Map<Integer, NavigateNode> guideNodeMap |
| | | ) { |
| | | // 防爆:条数限制 |
| | | if (maxPaths > 0 && pathCount.get() >= maxPaths) return; |
| | |
| | | // 扩展邻居(严格复用你自己的可行走方向规则) |
| | | ArrayList<NavigateNode> neighbors = extend_current_node(map, current); |
| | | if (neighbors == null || neighbors.isEmpty()) return; |
| | | neighbors = sortNeighborsByGuide(current, path, neighbors, guideStationIds, guideNodeMap); |
| | | |
| | | for (NavigateNode next : neighbors) { |
| | | // 防爆:条数限制 |
| | |
| | | depth + 1, |
| | | newCost, |
| | | maxDepth, maxPaths, maxCost, |
| | | pathCount |
| | | pathCount, |
| | | guideStationIds, |
| | | guideNodeMap |
| | | ); |
| | | |
| | | // 回溯 |
| | |
| | | |
| | | private String keyOf(NavigateNode n) { |
| | | return n.getX() + "_" + n.getY(); |
| | | } |
| | | |
| | | private Map<Integer, NavigateNode> buildGuideNodeMap(List<List<NavigateNode>> map, List<Integer> guideStationIds) { |
| | | Map<Integer, NavigateNode> guideNodeMap = new HashMap<>(); |
| | | if (map == null || map.isEmpty() || guideStationIds == null || guideStationIds.isEmpty()) { |
| | | return guideNodeMap; |
| | | } |
| | | for (Integer stationId : guideStationIds) { |
| | | if (stationId == null || guideNodeMap.containsKey(stationId)) { |
| | | continue; |
| | | } |
| | | NavigateNode stationNode = findStationNavigateNode(map, stationId); |
| | | if (stationNode != null) { |
| | | guideNodeMap.put(stationId, stationNode); |
| | | } |
| | | } |
| | | return guideNodeMap; |
| | | } |
| | | |
| | | private ArrayList<NavigateNode> sortNeighborsByGuide(NavigateNode current, |
| | | LinkedList<NavigateNode> path, |
| | | ArrayList<NavigateNode> neighbors, |
| | | List<Integer> guideStationIds, |
| | | Map<Integer, NavigateNode> guideNodeMap) { |
| | | if (current == null || neighbors == null || neighbors.size() <= 1 |
| | | || guideStationIds == null || guideStationIds.isEmpty() |
| | | || guideNodeMap == null || guideNodeMap.isEmpty()) { |
| | | return neighbors; |
| | | } |
| | | |
| | | Integer nextGuideStationId = resolveNextGuideStationId(path, guideStationIds); |
| | | if (nextGuideStationId == null) { |
| | | return neighbors; |
| | | } |
| | | NavigateNode guideTargetNode = guideNodeMap.get(nextGuideStationId); |
| | | if (guideTargetNode == null) { |
| | | return neighbors; |
| | | } |
| | | |
| | | neighbors.sort((left, right) -> compareGuideNeighbor(current, left, right, nextGuideStationId, guideTargetNode)); |
| | | return neighbors; |
| | | } |
| | | |
| | | private Integer resolveNextGuideStationId(LinkedList<NavigateNode> path, List<Integer> guideStationIds) { |
| | | if (path == null || path.isEmpty() || guideStationIds == null || guideStationIds.isEmpty()) { |
| | | return null; |
| | | } |
| | | |
| | | int cursor = 0; |
| | | Set<Integer> seen = new HashSet<>(); |
| | | for (NavigateNode node : path) { |
| | | Integer stationId = extractStationId(node); |
| | | if (stationId == null || !seen.add(stationId)) { |
| | | continue; |
| | | } |
| | | if (cursor < guideStationIds.size() && stationId.equals(guideStationIds.get(cursor))) { |
| | | cursor++; |
| | | } |
| | | } |
| | | if (cursor >= guideStationIds.size()) { |
| | | return null; |
| | | } |
| | | return guideStationIds.get(cursor); |
| | | } |
| | | |
| | | private int compareGuideNeighbor(NavigateNode current, |
| | | NavigateNode left, |
| | | NavigateNode right, |
| | | Integer nextGuideStationId, |
| | | NavigateNode guideTargetNode) { |
| | | int leftDirect = isGuideStation(left, nextGuideStationId) ? 0 : 1; |
| | | int rightDirect = isGuideStation(right, nextGuideStationId) ? 0 : 1; |
| | | if (leftDirect != rightDirect) { |
| | | return Integer.compare(leftDirect, rightDirect); |
| | | } |
| | | |
| | | int leftDistance = calcNodeCost(left, guideTargetNode); |
| | | int rightDistance = calcNodeCost(right, guideTargetNode); |
| | | if (leftDistance != rightDistance) { |
| | | return Integer.compare(leftDistance, rightDistance); |
| | | } |
| | | |
| | | int leftTurnCost = calcNodeExtraCost(current, left, guideTargetNode); |
| | | int rightTurnCost = calcNodeExtraCost(current, right, guideTargetNode); |
| | | if (leftTurnCost != rightTurnCost) { |
| | | return Integer.compare(leftTurnCost, rightTurnCost); |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | private boolean isGuideStation(NavigateNode node, Integer stationId) { |
| | | Integer nodeStationId = extractStationId(node); |
| | | return nodeStationId != null && nodeStationId.equals(stationId); |
| | | } |
| | | |
| | | private Integer extractStationId(NavigateNode node) { |
| | | if (node == null || !"devp".equals(node.getNodeType())) { |
| | | return null; |
| | | } |
| | | try { |
| | | JSONObject valueObj = JSON.parseObject(node.getNodeValue()); |
| | | return valueObj == null ? null : valueObj.getInteger("stationId"); |
| | | } catch (Exception ignore) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | public ArrayList<NavigateNode> extend_current_node(List<List<NavigateNode>> map, NavigateNode current_node) { |
| | |
| | | |
| | | for(String direction : directionList) { |
| | | if(direction.equals("top")) { |
| | | NavigateNode node = getValidNavigateNode(map, x - 1, y); |
| | | NavigateNode node = getValidNavigateNode(map, current_node, x - 1, y, direction); |
| | | if(node != null) { |
| | | neighbour_node.add(node); |
| | | } |
| | | }else if(direction.equals("bottom")) { |
| | | NavigateNode node = getValidNavigateNode(map, x + 1, y); |
| | | NavigateNode node = getValidNavigateNode(map, current_node, x + 1, y, direction); |
| | | if(node != null) { |
| | | neighbour_node.add(node); |
| | | } |
| | | }else if(direction.equals("left")) { |
| | | NavigateNode node = getValidNavigateNode(map, x, y - 1); |
| | | NavigateNode node = getValidNavigateNode(map, current_node, x, y - 1, direction); |
| | | if(node != null) { |
| | | neighbour_node.add(node); |
| | | } |
| | | }else if(direction.equals("right")) { |
| | | NavigateNode node = getValidNavigateNode(map, x, y + 1); |
| | | NavigateNode node = getValidNavigateNode(map, current_node, x, y + 1, direction); |
| | | if(node != null) { |
| | | neighbour_node.add(node); |
| | | } |
| | |
| | | } |
| | | |
| | | return neighbour_node; |
| | | } |
| | | |
| | | /** |
| | | * 邻接点校验:可达 + 方向一致(当前节点与下一节点对本次行走方向一致) |
| | | */ |
| | | public NavigateNode getValidNavigateNode(List<List<NavigateNode>> map, NavigateNode currentNode, int x, int y, String moveDirection) { |
| | | NavigateNode node = getValidNavigateNode(map, x, y); |
| | | if (node == null) { |
| | | return null; |
| | | } |
| | | |
| | | if (!isDirectionConsistent(currentNode, node, moveDirection)) { |
| | | return null; |
| | | } |
| | | |
| | | return node; |
| | | } |
| | | |
| | | public NavigateNode getValidNavigateNode(List<List<NavigateNode>> map, int x, int y) { |
| | |
| | | return node; |
| | | } |
| | | |
| | | private boolean isDirectionConsistent(NavigateNode currentNode, NavigateNode nextNode, String moveDirection) { |
| | | if (currentNode == null || nextNode == null) { |
| | | return false; |
| | | } |
| | | |
| | | if (moveDirection == null) { |
| | | return false; |
| | | } |
| | | |
| | | List<String> currentDirectionList = currentNode.getDirectionList(); |
| | | List<String> nextDirectionList = nextNode.getDirectionList(); |
| | | if (currentDirectionList == null || nextDirectionList == null) { |
| | | return false; |
| | | } |
| | | |
| | | // 当前节点允许向 moveDirection 出发,且下一节点在该方向上保持一致,才允许通行 |
| | | return currentDirectionList.contains(moveDirection) && nextDirectionList.contains(moveDirection); |
| | | } |
| | | |
| | | public NavigateNode findStationNavigateNode(List<List<NavigateNode>> map, int stationId) { |
| | | for(int x = 0; x < map.size(); x++) { |
| | | for(int y = 0; y < map.get(0).size(); y++) { |