package com.zy.asrs.wcs.core.utils; 
 | 
  
 | 
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 = new NavigateMapData(); 
 | 
        int[][] data = mapData.getData(); 
 | 
        this.map = data; 
 | 
    } 
 | 
  
 | 
    public NavigateSolution(Integer mapType, Integer lev, List<int[]> whitePoints, List<int[]> shuttlePoints) { 
 | 
        //载入地图指定层高地图 
 | 
        NavigateMapData mapData = new NavigateMapData(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------------------// 
 | 
  
 | 
} 
 |