我使用算法开始查找数组点头的路径。我有像这样的图像映射和节点:
红色节点是障碍物,黑色用于查找路径。我不知道为什么这条路要弯曲。我使用了这个库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);
}
与邻居节点的连接当前节点错误。
例如:
某些节点具有单向连接(图像向上)。
节点2具有邻居节点1,节点1不具有邻居节点2.
答案 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)
如果你有足够的地图内存,你仍然可以使用A *地图版
以这种方式查看here,避免图形混淆。找到更好的方法(不仅限于图形节点),但它更慢,内存要求更高。无论如何,您的问题看起来与节点的错误关联成本
看起来成本不是由物理距离定义的,而是图形中的节点距离,所以两个节点总是比一个对角线更昂贵,无论它们到底有多远。
这意味着它找到的路径最少,节点数不是最小距离,但我不使用图形 A * ,所以请记住这一点。如果您可以检查node.calculateDistanceBetweenNods()
函数或将节点设置为无缝网格(添加空节点)以更正此问题。但是没有经验,我只推测...
一些见解(但我不熟悉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);
}
}
}
你可以重新思考它。你会发现的。