带图像映射的星型算法(android)

时间:2014-08-04 14:15:11

标签: java algorithm path-finding a-star

我使用算法开始查找数组点头的路径。我有像这样的图像映射和节点:

enter image description here

红色节点是障碍物,黑色用于查找路径。我不知道为什么这条路要弯曲。我使用了这个库https://code.google.com/p/a-star-java/source/browse/AStar/src/aStar/?r=7,我更改了函数registerEdges。:

  private void registerEdges(ArrayList<Node> nodes) 
   {
       float currentDistX = 0;
       float currentDistY = 0;
       float distance = 0;

       for(int l = 0 ; l < nodes.size(); l++)
       {
           MINDISTN = Integer.MIN_VALUE;
           MINDISTS = Integer.MAX_VALUE;
           MINDISTE = Integer.MIN_VALUE;
           MINDISTW = Integer.MAX_VALUE;

           MINDISTNE = Integer.MAX_VALUE;
           MINDISTNW = Integer.MAX_VALUE;
           MINDISTSE = Integer.MAX_VALUE;
           MINDISTSW = Integer.MAX_VALUE;

           Node node = null;
           currentDistX = 0;
           currentDistY = 0;

           //System.out.println("current " + node.x + " " + node.y);
           for(int j = 0 ; j < map.size() ; j++)
           {
               if(l != j)
               {
                   node = map.get(l);


                   currentDistX = map.get(j).x - node.x;
                   currentDistY = map.get(j).y - node.y;

                   if(currentDistX == 0)
                   {
                       if(currentDistY < 0)
                       {
                           if(currentDistY > MINDISTN)
                           {
                               MINDISTN = currentDistY;
                               node.setNorth(map.get(j));
                               //System.out.println(currentDist + " n " + map.get(j).x + " " + map.get(j).y);
                           }
                       }
                       else if(currentDistY > 0)
                       {
                           if(currentDistY < MINDISTS)
                           {
                               //System.out.println(currentDist + " south " + map.get(j).x + " " + map.get(j).y);
                               MINDISTS = currentDistY;
                               node.setSouth(map.get(j));
                           }
                       }      
                   }           

                   if(currentDistY == 0)
                   {
                       if(currentDistX < 0)
                       {

                           if(currentDistX > MINDISTE)
                           {
                               MINDISTE = currentDistX;
                               node.setEast(map.get(j));

                               //System.out.println(currentDist + " e " + map.get(j).x + " " + map.get(j).y);
                           }
                       }
                       else if(currentDistX > 0)
                       {
                           //System.out.print("m " + MINDISTRIGHT);
                           if(currentDistX < MINDISTW)
                           {
                               MINDISTW = currentDistX;
                               node.setWest(map.get(j));
                               //System.out.println(currentDist + " w " + map.get(j).x + " " + map.get(j).y);
                           }
                       }
                   }

                   if(currentDistY != 0 && currentDistX != 0)
                   {

                       if(currentDistX > 0 && currentDistY > 0)
                       {
                           distance = node.calculateDistanceBetweenNods(map.get(j));

                           if(distance < MINDISTNE)
                           {
                               MINDISTNE = distance;
                               node.setNorthEast(map.get(j));

                               //System.out.println(currentDist + " e " + map.get(j).x + " " + map.get(j).y);
                           }
                       }
                       else if(currentDistX < 0 && currentDistY > 0)
                       {

                           distance = node.calculateDistanceBetweenNods(map.get(j));

                           if(distance < MINDISTNW)
                           {
                               MINDISTNW = distance;
                               node.setNorthWest(map.get(j));

                               //System.out.println(currentDist + " e " + map.get(j).x + " " + map.get(j).y);
                           }
                       }
                       else if(currentDistX <= 0 && currentDistY <= 0)
                       {

                           distance = node.calculateDistanceBetweenNods(map.get(j));

                           if(distance < MINDISTSW)
                           {
                               MINDISTSW = distance;
                               node.setSouthWest(map.get(j));

                               //System.out.println(currentDist + " e " + map.get(j).x + " " + map.get(j).y);
                           }
                       }
                       else if(currentDistX > 0 && currentDistY < 0)
                       {

                           distance = node.calculateDistanceBetweenNods(map.get(j));

                           if(distance < MINDISTSE)
                           {
                               MINDISTSE = distance;
                               node.setSouthEast(map.get(j));

                               //System.out.println(currentDist + " e " + map.get(j).x + " " + map.get(j).y);
                           }
                       }
                   }
               }
           }
    }

此功能查找North,South,West,East,N-East ...邻居节点。
估计路径:

public float getEstimatedDistanceToGoal(float startX, float startY, float goalX, float goalY) {         
            float dx = goalX - startX;
            float dy = goalY - startY;

            //float result = (float) (Math.sqrt((dx*dx)+(dy*dy)));

            //Optimization! Changed to distance^2 distance: (but looks more "ugly")

            float result = (float) (dx*dx)+(dy*dy);


            return (float) Math.sqrt(result);
    }

与邻居节点的连接当前节点错误。
例如:

enter image description here

某些节点具有单向连接(图像向上)。
节点2具有邻居节点1,节点1不具有邻居节点2.

3 个答案:

答案 0 :(得分:2)

您在答案中粘贴的代码对于二维路径搜索似乎有点复杂。

如果我理解你很好,你打算在一个8连接的网格中搜索图像中的最短路径,并且你试图使用A *来解决问题。我建议您使用搜索库,以便更清楚地组织搜索算法的不同组件。

在此基础上,如果你有A *的实现,你只需要定义:

  • 成本函数(根据您的问题描述,可能是点之间的欧氏距离)。
  • 转换函数(给定Point检索8个邻居,过滤由于地图图像中的障碍而无法访问的邻居。)
  • 您已在getEstimatedDistanceToGoal
  • 中实施的启发式功能

您可以查看Hipster library,它除了具有更清晰的结构外,还具有以动态方式生成图形节点的好处。这允许您节省大量内存,因为您在生成先验的大多数节点将不会在搜索过程中使用。

Here您可以找到使用迷宫进行2D搜索的代码示例。要使示例适应您的案例,唯一需要实现TransitionFunction来使用您的地图图像。该示例使用以下代码生成给定当前节点的邻居节点(函数Maze2D.validLocationsFrom(Point)):

public Collection<Point> validLocationsFrom(Point loc) {
   Collection<Point> validMoves = new HashSet<Point>();
   // Check for all valid movements
   for (int row = -1; row <= 1; row++) {
      for (int column = -1; column <= 1; column++) {
         try {
            //
            //TODO: Implement isFree(Point) to check in your map image
            //if a node is occupied or not.
            //
            if (isFree(new Point(loc.x + column, loc.y + row))) {
               validMoves.add(new Point(loc.x + column, loc.y + row));
            }
         } catch (ArrayIndexOutOfBoundsException ex) {
         // Invalid move!
         }
      }
   }
   validMoves.remove(loc);
   return validMoves;
}

在示例中,函数isFree(Point)查询迷宫以了解节点是否被占用。你只需要填写这个函数来查询地图图像而不是迷宫,就是这样!

我希望我的答案有所帮助,

答案 1 :(得分:1)

  1. 如果你有足够的地图内存,你仍然可以使用A *地图版

    以这种方式查看here,避免图形混淆。找到更好的方法(不仅限于图形节点),但它更慢,内存要求更高。

  2. 无论如何,您的问题看起来与节点的错误关联成本

    看起来成本不是由物理距离定义的,而是图形中的节点距离,所以两个节点总是比一个对角线更昂贵,无论它们到底有多远。

    这意味着它找到的路径最少,节点数不是最小距离,但我不使用图形 A * ,所以请记住这一点。如果您可以检查node.calculateDistanceBetweenNods()函数或将节点设置为无缝网格(添加空节点)以更正此问题。但是没有经验,我只推测...

  3. 一些见解(但我不熟悉JAVA ......)

    所以首先看一下你使用float表示当前距离,int表示它们与之比较的常数。此外,所有if 都没有处理浮动值!!! ,例如:

    if(currentDistX == 0)
    

    应该是这样的:

    if(fabs(currentDistX)<=1e-6)
    

    最后一件事我不知道JAVA是否具有<=&&的相同优先级,但我会觉得更安全

    if((currentDistX<=0.0)&&(currentDistY<=0.0))
    

    因为我在很多编译器之前已经多次烧过。

答案 2 :(得分:0)

我发现了一个错误。但是,没必要唯一的一个:

               if(currentDistY == 0)
               {
                   if(currentDistX < 0) <===== here, change to currentDistX > 0
                   {

                       if(currentDistX > MINDISTE)
                       {
                           MINDISTE = currentDistX;
                           node.setEast(map.get(j));

                           //System.out.println(currentDist + " e " + map.get(j).x + " " + map.get(j).y);
                       }
                   }
                   else if(currentDistX > 0) <======= here, change to currentDistX < 0
                   {
                       //System.out.print("m " + MINDISTRIGHT);
                       if(currentDistX < MINDISTW)
                       {
                           MINDISTW = currentDistX;
                           node.setWest(map.get(j));
                           //System.out.println(currentDist + " w " + map.get(j).x + " " + map.get(j).y);
                       }
                   }
               } 

你可以重新思考它。你会发现的。