protected double getG() { if (g_score == 0) { final JPSNode parent = came_from; g_score = parent != null ? parent.getG() + parent.getMoveCost(this) : 0.0D; } return g_score; }
@Override public JPSNode clone() { // TODO to override object clone() this should implement Cloneable. // Otherwise it's better to call it something else. like copy(). JPSNode clone = new JPSNode(x, y); clone.came_from = this; return clone; }
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; }
public double getMoveCost(JPSNode node) { if (node == null) return 0; double x = node.getX(), y = node.getY(), px = getX(), py = getY(); double steps = getSteps(x, y, px, py); return x == px || y == px ? steps : (double) steps * 1; }
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); }
private JPSNode[] getJPSNeighbours(JPSNode current, List<IObstacle> obsList) { double x = current.getX(); double y = current.getY(); LinkedList<JPSNode> nodes = new LinkedList<JPSNode>(); JPSNode parent = current.came_from; if (parent != null) { // determines whether to prune neighbors JPSNode norm = normalizeDirection(x, y, parent.getX(), parent.getY()); double dx = norm.getX() * coordinateScaling; double dy = norm.getY() * coordinateScaling; JPSNode temp = new JPSNode(current); if (((int) dx & (int) dy) != 0) { // diagonal direction // check straight directions in the direction of the diagonal move if (walkable(temp.setPosition(x, y + dy))) nodes.add(new JPSNode(temp)); if (walkable(temp.setPosition(x + dx, y))) nodes.add(new JPSNode(temp)); if (walkable(temp.setPosition(x + dx, y + dy))) nodes.add(new JPSNode(temp)); // forced neighbor checks if (!walkable(temp.setPosition(x - dx, y))) nodes.add(new JPSNode(temp.shift(0, dy))); if (!walkable(temp.setPosition(x, y - dy))) nodes.add(new JPSNode(temp.shift(dx, 0))); } else { // straight direction if (walkable(temp.setPosition(x + dx, y + dy))) { nodes.add(new JPSNode(temp)); // forced neighbor checks if (!walkable(temp.setPosition(x + dy, y + dx))) nodes.add(new JPSNode(temp.shift(dx, dy))); if (!walkable(temp.setPosition(x - dy, y - dx))) nodes.add(new JPSNode(temp.shift(dx, dy))); } } } else { // no parent, return all that aren't blocked JPSNode[] ns = new JPSNode[] { new JPSNode(x, y - coordinateScaling), new JPSNode(x + coordinateScaling, y - coordinateScaling), new JPSNode(x + coordinateScaling, y), new JPSNode(x + coordinateScaling, y + coordinateScaling), new JPSNode(x, y + coordinateScaling), new JPSNode(x - coordinateScaling, y + coordinateScaling), new JPSNode(x - coordinateScaling, y), new JPSNode(x - coordinateScaling, y - coordinateScaling) }; for (int i = 0; i < ns.length; i++) { if (walkable(ns[i])) nodes.add(ns[i]); } } return nodes.toArray(new JPSNode[nodes.size()]); }
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; }