RCP:gef智能寻路算法(A star)

简介: 本路由继承自AbstactRouter,参数只有EditPart(编辑器内容控制器),gridLength(寻路用单元格大小),style(FLOYD,FLOYD_FLAT,FOUR_DIR)。 字符集编码为GBK,本文只做简单的代码解析,源码戳我 如果源码不全,可以联系本人。

本路由继承自AbstactRouter,参数只有EditPart(编辑器内容控制器),gridLength(寻路用单元格大小),style(FLOYD,FLOYD_FLAT,FOUR_DIR)。

字符集编码为GBK,本文只做简单的代码解析,源码戳我

如果源码不全,可以联系本人。

算法实现主要有三:

1、Astar单向寻路

2、地图预读

3、弗洛伊德平滑算法

 

Astar寻路的实现:

ANode minFNode = null;
        while (true) {
            minFNode = findMinNode(openList);
            openList.remove(minFNode);
            closedList.add(minFNode);
            if (minFNode == null || minFNode.equals(endNode))
                break;
            search(minFNode, openList, closedList, startNode, endNode);
        }



private void search(ANode node, List<ANode> openList,
            List<ANode> closedList, ANode startNode, ANode endNode) {
        ANode[] nodes = findAroundNode(node);
        for (int i = 0, len = nodes.length; i < len; i++) {
            if (nodes[i].getLevel() == ANodeLevel.DEAD)
                continue;
            nodes[i].g = (i > 3 ? nodes[i].getLevel().RE
                    : nodes[i].getLevel().BE) + node.g;
            nodes[i].h = caculateH(nodes[i], endNode);
            if (closedList.contains(nodes[i]))
                continue;
            if (!openList.contains(nodes[i])) {
                openList.add(nodes[i]);
                nodes[i].setParent(node);
            } else if (openList.contains(nodes[i])) {
                int idx = openList.indexOf(nodes[i]);
                ANode n = openList.get(idx);
                if (nodes[i].g < n.g) {
                    openList.remove(idx);
                    closedList.add(n);
                    nodes[i].setParent(n.getParent());
                    openList.add(idx, nodes[i]);
                }
            }
        }
    }

 

在网上大部分版本的Astar算法里,障碍只有两个参考值,即是可通过和不可通过

但在实际情况里,有可能会有较难度过的小溪,难以度过的河流,不能跨越的深涧,于是我在算法里引入了难易度概念,由ANodeLevel体现。

 

package galaxy.ide.configurable.editor.gef.router;

/**
 * 节点等级,RE直角边,BE斜角边
 * 
 * @author caiyu
 * @date 2014-5-15
 */
public enum ANodeLevel {
    EASY(10, 14), NORMAL(20, 28), HARD(50, 68), DEAD(2000, 2800);
    /**
     * 直角边
     */
    public final int RE;
    /**
     * 斜角边
     */
    public final int BE;

    ANodeLevel(int RE, int BE) {
        this.RE = RE;
        this.BE = BE;
    }
}

 

引入了四个难易程度,当然,这些难易程度自己可以调整。

障碍的难易程度是预读的,体现在代码:

    private void preReadingNodes(Point startPoint) {
        Rectangle r;
        for (Object c : this.editPart.getChildren()) {
            if (c instanceof GraphicalEditPart) {
                r = ((GraphicalEditPart) c).getFigure().getBounds();
                preReader.read(r, startPoint, D);
            }
        }
    }

预读器preReader源码如下:

    public void read(Rectangle r, Point startPoint, final int D) {
        ANodeLevel level = ANodeLevel.HARD;
        if (r.contains(this.startPoint) || r.contains(this.endPoint))
            level = ANodeLevel.NORMAL;

        int xS = ANodePreReader.calculateIndex(r.x, startPoint.x, D);
        int xE = ANodePreReader
                .calculateIndex(r.x + r.width(), startPoint.x, D);
        int yS = ANodePreReader.calculateIndex(r.y, startPoint.y, D);
        int yE = ANodePreReader.calculateIndex(r.y + r.height(), startPoint.y,
                D);
        Map<Integer, ANodeLevel> map;
        for (int x = xS; x < xE; x++) {
            for (int y = yS; y < yE; y++) {
                map = pool.get(x);
                if (map == null) {
                    map = new HashMap<Integer, ANodeLevel>();
                    pool.put(x, map);
                }
                map.put(y, level);
            }
        }
    }

    public ANode getNode(int x, int y) {
        ANode node = new ANode(x, y);
        Map<Integer, ANodeLevel> map = pool.get(x);
        node.setLevel(map == null ? ANodeLevel.EASY
                : map.get(y) == null ? ANodeLevel.EASY : map.get(y));
        return node;
    }


    public static int calculateIndex(int v1, int v2, int distance) {
        int offset = (v1 - v2) % distance;
        return offset > 0 ? (v1 - v2) / distance + 1 : offset == 0 ? (v1 - v2)
                / distance : (v1 - v2) / distance - 1;
    }

 

完成了以上,即可以实现智能绘图,应用该路由 new AStarConnectionRouter2(editPart, 20, AStarConnectionRouter.NONE);(不会在GEF中应用路由器的去看《GEF whole update》这本书)

如图所示:

 

 

可以看出,这个算法还有缺陷,并不平滑。我们加入弗洛伊德平滑算法new AStarConnectionRouter2(editPart, 20, AStarConnectionRouter.FLOYD);

,效果如图:

 

弗洛伊德平滑算法的原理:

1、如果A、B、C三点在同一直线上,视为三点共线,则去除B点

2、清理所有共线点之后,遍历任一点和其他点之间有无障碍物,如果没有,则去除两点之间的全部点。

算法实现:

    /**
     * 弗洛伊德平滑处理
     * 
     * @param D
     * @param startPoint
     * 
     * @param points
     */
    public void floyd(ANode node, Point startPoint, int D) {
        if ((this.style & FLOYD_SIMPLIFY) != FLOYD_SIMPLIFY
                && (this.style & FLOYD) != FLOYD)
            return;
        ANode fatherNode, currentNode = node, grandNode;
        // 去除共线
        while (true) {
            fatherNode = currentNode.getParent();
            if (fatherNode == null)
                break;
            grandNode = fatherNode.getParent();
            if (grandNode == null)
                break;
            if (fatherNode.xIndex - currentNode.xIndex == grandNode.xIndex
                    - fatherNode.xIndex
                    && fatherNode.yIndex - currentNode.yIndex == grandNode.yIndex
                            - fatherNode.yIndex) {
                currentNode.setParent(grandNode);
            } else
                currentNode = fatherNode;
        }
        currentNode = node;

        if ((this.style & FLOYD) != FLOYD)
            return;
        // 去除拐点
        while (true) {
            fatherNode = currentNode.getParent();
            if (fatherNode == null)
                break;
            while (true) {
                grandNode = fatherNode.getParent();
                if (grandNode == null)
                    break;
                if (linkable(currentNode, grandNode, startPoint, D)) {
                    currentNode.setParent(grandNode);
                }
                fatherNode = grandNode;
            }
            currentNode = currentNode.getParent();
            if (currentNode == null)
                break;
        }
    }

 

但是,上图的效果并不美观,有两个参考方案:

1、自己重写ConnectionFigure,使拐点圆滑

2、Astar算法只参考上下左右四个方向

只参考四个方向的使用例子new AStarConnectionRouter2(editPart, 20, AStarConnectionRouter.FLOYD| AStarConnectionRouter.FOUR_DIR);

如图所示:

 

以上,即实现了全部效果。

注意,在RouterStyle里有个TEST选项,该选项是测试使用,使用过程中会有大量bug。

new AStarConnectionRouter2(editPart, 20,
AStarConnectionRouter.FOUR_DIR
| AStarConnectionRouter.FLOYD_SIMPLIFY
| AStarConnectionRouter.TEST);

该测试用于展示在寻路过程中AStar算法遍历到的节点,如图所示:

 

 

 

下一次再实现一个圆滑的弧线拐角,再来和大家分享。

 

源码下载请移步:http://pan.baidu.com/s/1hqgNN2s

 

 

 

 

 

 

 

 

 

 

 

 

目录
相关文章
|
5月前
|
机器学习/深度学习 人工智能 监控
AI算法分析,智慧城管AI智能识别系统源码
AI视频分析技术应用于智慧城管系统,通过监控摄像头实时识别违法行为,如违规摆摊、垃圾、违章停车等,实现非现场执法和预警。算法平台检测街面秩序(出店、游商、机动车、占道)和市容环境(垃圾、晾晒、垃圾桶、路面不洁、漂浮物、乱堆物料),助力及时处理问题,提升城市管理效率。
119 4
AI算法分析,智慧城管AI智能识别系统源码
|
5月前
|
机器学习/深度学习 算法 决策智能
智能解决装箱问题:使用优化算法实现高效包装
装箱问题(Bin Packing Problem)是组合优化领域中的一个经典问题,主要涉及如何将一系列对象高效地装入有限数量的容器(或“箱”)中,同时满足特定的约束条件。这个问题的目标是最小化所需使用的箱子数量或者最大化箱子的装载效率,以减少空间或资源的浪费。
|
5月前
|
机器学习/深度学习 算法
【Matlab智能算法】PSO优化(双隐层)BP神经网络算法
【Matlab智能算法】PSO优化(双隐层)BP神经网络算法
|
1天前
|
存储
基于遗传算法的智能天线最佳阵列因子计算matlab仿真
本课题探讨基于遗传算法优化智能天线阵列因子,以提升无线通信系统性能,包括信号质量、干扰抑制及定位精度。通过MATLAB2022a实现的核心程序,展示了遗传算法在寻找最优阵列因子上的应用,显著改善了天线接收功率。
|
1月前
|
机器学习/深度学习 算法 Python
群智能算法:深入解读人工水母算法:原理、实现与应用
近年来,受自然界生物行为启发的优化算法备受关注。人工水母算法(AJSA)模拟水母在海洋中寻找食物的行为,是一种新颖的优化技术。本文详细解读其原理及实现步骤,并提供代码示例,帮助读者理解这一算法。在多模态、非线性优化问题中,AJSA表现出色,具有广泛应用前景。
|
2月前
|
算法
互动游戏解决遇到问题之基于射线投射寻路算法的问题如何解决
互动游戏解决遇到问题之基于射线投射寻路算法的问题如何解决
|
3月前
|
机器学习/深度学习 数据采集 算法
Python实现WOA智能鲸鱼优化算法优化支持向量机分类模型(SVC算法)项目实战
Python实现WOA智能鲸鱼优化算法优化支持向量机分类模型(SVC算法)项目实战
271 4
|
3月前
|
机器学习/深度学习 数据采集 算法
Python实现WOA智能鲸鱼优化算法优化支持向量机回归模型(LinearSVR算法)项目实战
Python实现WOA智能鲸鱼优化算法优化支持向量机回归模型(LinearSVR算法)项目实战
173 2
|
3月前
|
机器学习/深度学习 数据采集 算法
Python实现SSA智能麻雀搜索算法优化支持向量机回归模型(SVR算法)项目实战
Python实现SSA智能麻雀搜索算法优化支持向量机回归模型(SVR算法)项目实战
209 1
|
3月前
|
机器学习/深度学习 数据采集 算法
Python实现SSA智能麻雀搜索算法优化支持向量机分类模型(SVC算法)项目实战
Python实现SSA智能麻雀搜索算法优化支持向量机分类模型(SVC算法)项目实战
204 1

热门文章

最新文章