private boolean walkable(JPSNode node) { if (node.equals(goal)) { return !AbstractObstacle.isInsideObstacleList(obsList, node, 0) && shape.isInside(simulationDim, node); } else { return !AbstractObstacle.isInsideObstacleList(obsList, node, safetyDistance) && shape.isInside(simulationDim, node); } }
private JPSNode retrieveInstance(HashSet<JPSNode> openSet, JPSNode node) { if (node == null) return null; final Iterator<JPSNode> nI = openSet.iterator(); while (nI.hasNext()) { final JPSNode n = nI.next(); if (node.equals(n)) return n; } return null; }
private JPSNode jump(JPSNode node, JPSNode parent, JPSNode goal) { double x = node.getX(), y = node.getY(), px = parent.getX(), py = parent.getY(); double dx = (x - px); double dy = (y - py); // Log.e("Coordinatescaling: " + coordinateScaling); // Log.e("dy: " + dy + " dx: " + dx); // Log.e("JUMP! node: " + node.toString() + " parent: " + parent.toString() + " dx: " + dx + " // dy: " + dy); if (!walkable(node)) // check blocked return null; if (node.equals(goal)) // reached goal return new JPSNode(node); // resolve forced neighbors JPSNode temp = new JPSNode(node); if (((int) dx & (int) dy) != 0) { // diagonal if ((walkable(temp.setPosition(x - dx, y + dy)) && !walkable(temp.setPosition(x - dx, y))) || (walkable(temp.setPosition(x + dx, y - dy)) && !walkable(temp.setPosition(x, y - dy)))) { return new JPSNode(node); } // recurse JPSNode h = jump(node.derive(dx, 0), node, goal); if (h != null) return new JPSNode(node); JPSNode v = jump(node.derive(0, dy), node, goal); if (v != null) return new JPSNode(node); } else if (dx == 0) { // vertical, dx = 0, dy = 1 or -1 if ((walkable(temp.setPosition(x + coordinateScaling, y + dy)) && !walkable(temp.setPosition(x + coordinateScaling, y))) || (walkable(temp.setPosition(x - coordinateScaling, y + dy)) && !walkable(temp.setPosition(x - coordinateScaling, y)))) { return new JPSNode(node); } } else { // horizontal, dx = 1 or -1, dy = 0 if ((walkable(temp.setPosition(x + dx, y + coordinateScaling)) && !walkable(temp.setPosition(x, y + coordinateScaling))) || (walkable(temp.setPosition(x + dx, y - coordinateScaling)) && !walkable(temp.setPosition(x, y - coordinateScaling)))) { return new JPSNode(node); } } return jump(node.derive(dx, dy), node, goal); }
public List<Position> getShortestPathJumpPointsSearch( Position startPos, Position endPos, double safetyDistance) { this.safetyDistance = safetyDistance; JPSNode start = new JPSNode(startPos.getX(), startPos.getY()); goal = new JPSNode(endPos.getX(), endPos.getY()); HashSet<JPSNode> closedSet = new HashSet<JPSNode>(); HashSet<JPSNode> openSet = new HashSet<JPSNode>(); openSet.add(start); JPSNode current = start; double lowScore = Integer.MAX_VALUE; while (!openSet.isEmpty()) { lowScore = Integer.MAX_VALUE; for (JPSNode n : openSet) { double score = n.g_score; if (score < lowScore) { current = n; lowScore = score; } else if (score == lowScore) { // TODO (==) is less good for float equality // if(Math.abs(score - lowScore) < epsilon) // epsilon should be 0.000001 something if (n != current) { current = n; } } } // Log.v("openset" + openSet); //// Log.v("closedSet" + closedSet); //// Log.v("g_score" + current.g_score); //// Log.v("f_score" + current.f_score); // Log.v("current: " + current); // Log.v("--------"); if (current.equals(goal)) { return reconstructPath(current); } openSet.remove(current); closedSet.add(current); for (JPSNode neighbour : getJPSNeighbours(current, obsList)) { JPSNode jumpPoint = jump(neighbour, current, goal); if (jumpPoint != null) { if (closedSet.contains(jumpPoint)) continue; if (!openSet.contains(jumpPoint)) { jumpPoint.came_from = current; openSet.add(jumpPoint); } else if ((current.getG() + current.getMoveCost(jumpPoint)) < jumpPoint.getG()) { // G score of node with current node as it's parent JPSNode instanceNode = retrieveInstance(openSet, jumpPoint); if (instanceNode != null) instanceNode.came_from = current; } } } } Log.e( "Failed to find path to target! Start: " + start + " End: " + endPos + " obsList: " + obsList + " Dimension: " + simulationDim + " Shape: " + shape); return null; }