| package com.zy.asrs.wcs.core.utils; | 
|   | 
| import com.zy.asrs.framework.common.SpringUtils; | 
| import com.zy.asrs.wcs.core.model.NavigateNode; | 
|   | 
| import java.util.ArrayList; | 
| import java.util.List; | 
| import java.util.PriorityQueue; | 
|   | 
| /** | 
|  * 四向库核心 | 
|  * A*算法实现类 | 
|  */ | 
| public class NavigateSolution { | 
|   | 
|     // -1 -> 墙壁, 1 -> 起点  2 -> 终点  3-> 母轨  4->站点 | 
|   | 
|     int[][] map = {{}}; | 
|   | 
|     public NavigateSolution() { | 
|         //载入地图 | 
|         NavigateMapData mapData = SpringUtils.getBean(NavigateMapData.class); | 
|         mapData.setLev(1); | 
|         int[][] data = mapData.getData(); | 
|         this.map = data; | 
|     } | 
|   | 
|     public NavigateSolution(Integer mapType, Integer lev, List<int[]> whitePoints, List<int[]> shuttlePoints) { | 
|         //载入地图指定层高地图 | 
|         NavigateMapData mapData = SpringUtils.getBean(NavigateMapData.class); | 
|         mapData.setLev(lev); | 
|         int[][] data = mapData.getDataFromRedis(mapType, whitePoints, shuttlePoints); | 
|         if (data == null) { | 
|             data = mapData.getData(mapType, whitePoints, shuttlePoints); | 
|         } | 
|         this.map = data; | 
|     } | 
|   | 
|     public NavigateSolution(int[][] data) { | 
|         this.map = data; | 
|     } | 
|   | 
|     // Open表用优先队列 | 
|     public PriorityQueue<NavigateNode> Open = new PriorityQueue<NavigateNode>(); | 
|     //Close表用普通的数组 | 
|     public ArrayList<NavigateNode> Close = new ArrayList<NavigateNode>(); | 
|     //Exist表用来存放已经出现过的结点。 | 
|     public ArrayList<NavigateNode> Exist = new ArrayList<NavigateNode>(); | 
|   | 
|     public NavigateNode astarSearch(NavigateNode start, NavigateNode end) { | 
|         //把第一个开始的结点加入到Open表中 | 
|         this.Open.add(start); | 
|         //把出现过的结点加入到Exist表中 | 
|         this.Exist.add(start); | 
|         //主循环 | 
|         while (Open.size() > 0) { | 
|             //取优先队列顶部元素并且把这个元素从Open表中删除 | 
|             NavigateNode current_node = Open.poll(); | 
|             //将这个结点加入到Close表中 | 
|             Close.add(current_node); | 
|             //对当前结点进行扩展,得到一个四周结点的数组 | 
|             ArrayList<NavigateNode> neighbour_node = extend_current_node(current_node); | 
|             //对这个结点遍历,看是否有目标结点出现 | 
|             for (NavigateNode node : neighbour_node) { | 
|                 // G + H + E (对启发函数增加去拐点方案calcNodeExtraCost) | 
|                 int gCost = calcNodeCost(current_node, node) * calcNodeExtraCost(current_node, node, end); | 
|                 if (node.getX() == end.getX() && node.getY() == end.getY()) {//找到目标结点就返回 | 
|                     //init_node操作把这个邻居结点的父节点设置为当前结点 | 
|                     //并且计算出G, F, H等值 | 
|                     node.init_node(current_node, end); | 
|                     return node; | 
|                 } | 
|   | 
|                 //(对启发函数增加去拐点方案calcNodeExtraCost) | 
|                 if (is_exist(node)) { | 
|                     if (gCost < node.getG()) { | 
|                         node.setFather(current_node); | 
|                         node.setG(gCost); | 
|                         node.setF(node.getG() + node.getH()); | 
|                     } | 
|                 }else { | 
|                     //没出现过的结点加入到Open表中并且设置父节点 | 
|                     //进行计算对G, F, H 等值 | 
|                     node.init_node(current_node, end); | 
|                     node.setG(gCost); | 
|                     node.setH(calcNodeCost(node, end)); | 
|                     node.setF(node.getG() + node.getH()); | 
|   | 
|                     Open.add(node); | 
|                     Exist.add(node); | 
|                 } | 
|             } | 
|         } | 
|         //如果遍历完所有出现的结点都没有找到最终的结点,返回null | 
|         return null; | 
|     } | 
|   | 
|   | 
|     public ArrayList<NavigateNode> extend_current_node(NavigateNode current_node) { | 
|         //获取当前结点的x, y | 
|         int x = current_node.getX(); | 
|         int y = current_node.getY(); | 
|         //如果当前结点的邻结点合法,就加入到neighbour_node | 
|         ArrayList<NavigateNode> neighbour_node = new ArrayList<NavigateNode>(); | 
| //        if (map[x][y] == 0 || map[x][y] == 3) { | 
| //            //只有子轨和母轨才能进行左右移动 | 
| //            if (is_valid(x, y + 1)) | 
| //            { | 
| //                Node node = new Node(x, y + 1); | 
| //                neighbour_node.add(node); | 
| //            } | 
| //            if (is_valid(x, y - 1)) | 
| //            { | 
| //                Node node = new Node(x, y - 1); | 
| //                neighbour_node.add(node); | 
| //            } | 
| //        } | 
| // | 
| //        if (map[x][y] == 3) { | 
| //            //只有母轨才能进行上下移动 | 
| //            if (is_valid(x + 1, y)) | 
| //            { | 
| //                Node node = new Node(x + 1, y); | 
| //                neighbour_node.add(node); | 
| //            } | 
| //            if (is_valid(x - 1, y)) | 
| //            { | 
| //                Node node = new Node(x -1, y); | 
| //                neighbour_node.add(node); | 
| //            } | 
| //        } | 
|         if (map[x][y] == 3) { | 
|             //母轨才能进行左右移动 | 
|             if (is_valid(x, y + 1)) | 
|             { | 
|                 NavigateNode node = new NavigateNode(x, y + 1); | 
|                 neighbour_node.add(node); | 
|             } | 
|             if (is_valid(x, y - 1)) | 
|             { | 
|                 NavigateNode node = new NavigateNode(x, y - 1); | 
|                 neighbour_node.add(node); | 
|             } | 
|         } | 
|   | 
|         if (map[x][y] == 0 || map[x][y] == 3 || map[x][y] == 4 || map[x][y] == 5) { | 
|             //子轨和母轨、输送线、充电桩才能进行上下移动 | 
|             if (is_valid(x + 1, y)) | 
|             { | 
|                 NavigateNode node = new NavigateNode(x + 1, y); | 
|                 neighbour_node.add(node); | 
|             } | 
|             if (is_valid(x - 1, y)) | 
|             { | 
|                 NavigateNode node = new NavigateNode(x -1, y); | 
|                 neighbour_node.add(node); | 
|             } | 
|         } | 
|   | 
|         return neighbour_node; | 
|     } | 
|   | 
|     public boolean is_valid(int x, int y) { | 
|         // 如果结点的位置小于0,则不合法 | 
|         if (map[x][y] < 0) return false; | 
|         for (NavigateNode node : Exist) { | 
|             //如果结点出现过,不合法 | 
|             if (node.getX() == x && node.getY() == y) { | 
|                 return false; | 
|             } | 
|             if (is_exist(new NavigateNode(x, y))) { | 
|                 return false; | 
|             } | 
|         } | 
|         //以上情况都没有则合法 | 
|         return true; | 
|     } | 
|   | 
|     public boolean is_exist(NavigateNode node) | 
|     { | 
|         for (NavigateNode exist_node : Exist) { | 
|             if (node.getX() == exist_node.getX() && node.getY() == exist_node.getY()) { | 
|                 return true; | 
|             } | 
|         } | 
|         return false; | 
|     } | 
|   | 
|     //------------------A*启发函数------------------// | 
|   | 
|     //计算通过现在的结点的位置和最终结点的位置计算H值(曼哈顿法:坐标分别取差值相加) | 
|     private int calcNodeCost(NavigateNode node1, NavigateNode node2) { | 
|         return Math.abs(node2.getX() - node1.getX()) + Math.abs(node2.getY() - node1.getY()); | 
|     } | 
|   | 
|     //去除拐点算法,给直线增加优先级 | 
|     private int calcNodeExtraCost(NavigateNode currNode, NavigateNode nextNode, NavigateNode endNode) { | 
|         // 第一个点或直线点 | 
|         if (currNode.getFather() == null || nextNode.getX() == currNode.getFather().getX() | 
|                 || nextNode.getY() == currNode.getFather().getY()) { | 
|             return 0; | 
|         } | 
|   | 
|         // 拐向终点的点 | 
|         if (nextNode.getX() == endNode.getX() || nextNode.getY() == endNode.getY()) { | 
|             return 1; | 
|         } | 
|   | 
|         // 普通拐点 | 
|         /* | 
|         拐点判断逻辑 | 
|         拿到父节点和下一节点 | 
|         通过判断父节点和下一节点的x数据和y数据都不相同时,则表明当前坐标是一个拐点 | 
|          */ | 
|         return 2; | 
|     } | 
|   | 
|     //------------------A*启发函数-end------------------// | 
|   | 
| } |